Kerio Control и Remote Desktop Services — авторизуем и считаем терминальных пользователей +5


Данный материал посвящён решению проблемы учёта и контроля пользователей, работающих на сервере RDS (бывший терминальный сервер) и получающих доступ в интернет через шлюз Kerio Control.



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

Основная проблема возникает, когда сервер RDS сконфигурирован как «RD Session Host» — в этом случае пользователи подключаются к сети, используя один исходящий IP-адрес на всех (адрес сервера RDS), что приводит к классической ситуации «кто первый встал, того и тапки». Только в данном случае тапки достаются последнему.

Что у нас есть:
— есть домен AD (пусть будет habr.local);
— сервер RDS на базе Windows Server 2012(r2) сконфигурирован как «RD Session Host»;
— на сервере RDS в качестве браузера используется штатный Internet Explorer 11;
— шлюз на базе Kerio Control (пусть его имя будет kerio-fw).

Описанная схема работает так же и для «классического» терминального сервера на базе Windows Server 2008 R2.

Приступим.

Как уже написано, основная проблема — в том, что пользователи в количестве большем, чем один, пытаются авторизоваться на шлюзе с одного IP-адреса. Для решения этой проблемы разработчики шлюза предлагают несколько способов, точнее — два: использование непрозрачного прокси-сервера, и принудительная авторизация в браузере.
Из них более-менее работает лишь первый — непрозрачный прокси. Увы, далеко не все программы вообще знаю, что такое прокси-сервер, а уж прозрачно авторизоваться в нём — могут единицы.

Часть первая: «Поиск и обретение».

После мучительных попыток скрестить ежа с ужом пришло озарение: схема «один IP -> много пользователей» работать нормально не будет. Стало легче, т.к. обозначился путь выхода: «Свой IP для каждого даром, и пусть никто не уйдет обиженным» .

Логичная для этой ситуации схема VDI нас не устраивала, но интернет быстро подсказал решение: Remote Desktop IP Virtualization.
Коротко: данная технология появилась в Windows Server 2008 R2 и позволяет назначить индивидуальный IP-адрес либо всей сессии пользователя — режим «per-session», либо любому экземпляру запускаемых пользователями программ из списка — режим «per-program».

То, что надо, короче.

Поднимаем Remote Desktop IP Virtualization
В нашем случае оптимально будет использовать режим «per-session», что избавляет от необходимости включать в список все программы, которым нужен доступ в сеть.
Режим настраивается просто: применяем на нужные серверы следующую политику GPO:



Не забываем указать свою подсеть, в которой находится сетевой адаптер, который нужно виртуализировать. Если адаптеров несколько — указываем только один (больше одного не поддерживается).

Замечание 1: по умолчанию «виртуальные» IP-адреса запрашиваются у DHCP-сервера, и большинство (возможно что и все) не-microsoft DHCP-серверы некорректно обрабатывают такие запросы. Т.е. вам нужен включённый в домен Windows-based сервер с ролью «DHCP Server».

Замечание 2: если по каким-то причинам развернуть Windows-based DHCP-сервер не представляется возможным, можно с помощью опять же групповых политик назначить для сервера диапазон IP, из которого он сам себе будет назначать «виртуальные» IP, никого не спрашивая. В этом случае вся ответственность за возможные коллизии лежит на вас.

Замечание 3: Пул адресов DHCP-сервера должен быть достаточным для обеспечения адресами всех ваших «виртуальных» пользователей.

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

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

Часть вторая марлезонского балета — «Автоматизируй это».

Так как сессиям пользователей IP-адреса назначаются случайным образом, то привязать пользователя в Kerio Control к конкретному адресу возможности нет. Значит, нужно каким-то образом авторизовать пользователя на шлюзе.
При этом стояла задача делать всё максимально прозрачно — никаких окошек запроса логина и пароля, ничего, что бы пользователь мог сделать не так. А то ведь он обязательно сделает всё не так, дай только ему возможность.

К счастью, шлюз Kerio Control легко подключается к домену и поддерживает прозрачную NTLM-авторизацию браузером.
NTLM-магия
Настройки Kerio Control:



Политика GPO:

И если пользователи пользуются только браузером, то на этом можно и остановиться.

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

Решение очевидное, и оно описано в документации на сайте разработчика — logon script.
Вот тут была уничтожена неделя рабочего времени (с перерывами на обед).
О чём речь?
Разработчики предлагают выполнять во время входа пользователя в систему VBS-скрипт следующего содержания:
Dim oIE
Set oIE = CreateObject("InternetExplorer.Application")
oIE.Visible = False
oIE.Fullscreen = False
oIE.Toolbar = True
oIE.Statusbar = True
oIE.Navigate("http://www.google.com/")
WScript.Sleep(30000)
oIE.quit
Т.е. создать фоновый объект Internet Explorer и перенаправить его на произвольную страницу в интернете, после чего подождать, пока этот объект авторизует сессию пользователя на шлюзе, и закрыть его.

Особо продвинутые одмины в интернетах используют перенаправление на страницу авторизации шлюза
oIE.Navigate("https://kerio-fw.habr.local:4081/login/?NTLM=1")
где клиент по идее авторизуется без необходимости бродить по интернетам.

Дело в том, что указанный скрипт, как и все его модификации в интернетах — не работает корректно в версиях Windows старше 7 (и соответствующих серверных версиях). В зависимости от ритма удара в бубен авторизация либо не происходит, либо окно демонстрируется пользователю (и пугает его), либо зависает процесс iexplore.exe — в общем, всё плохо.

Интенсивным использованием метода «научного тыка» был найден виновник — User Account Control, он же UAC. Так как понижать защищённость системы желания не было, то ещё какое-то время было потрачено на то, что бы убедится — без его отключения скрипт нормально работать не будет. Убедились.

К счастью, изначально были задействованы и настроены Software Restriction Policies (Политики ограничения использования программ), по этому после недолгих моральных страданий было решено пожертвовать UAC-ом во имя светлого будущего.
Жертвуем UAC-ом.
После этого скрипты заработали как надо, были почищены от избыточного кода и заняли своё место в скриптохранилище.
Вот они, лежат...
KerioConnectLogon.vbs
Dim IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
Wscript.Sleep(3000)
IE.Navigate2("https://kerio-fw.habr.local:4081/login/?NTLM=1")
Wscript.Sleep(20000)
IE.Quit
KerioConnectLogout.vbs
Dim IE
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = False
IE.Navigate2("https://kerio-fw.habr.local:4081/logout")
Wscript.Sleep(3000)
IE.Quit

В процессе тестирование выяснилось ещё пару нюансов:
— если назначать запуск скрипта с помощью GPO (logon script), то он периодически не выполнял авторизацию и зависал — возможно, потому что сессии не успевал назначиться IP-адрес, или по какой-то другой причине;
— если пользователь отключался от шлюза по тайм-ауту бездействия, то он понятное дело терял подключение к интернету;
— когда пользователь завершал свой сеанс на терминальном сервере, его IP-адрес мог быть выделен другому вошедшему пользователю до того, как шлюз отключит предыдущего по тайм-ауту.

Всё это привело к схеме, когда для авторизации пользователя на шлюзе создаётся (обновляется) отдельное задание в планировщике задач Windows (средствами GPO), запускающее указанный выше скрипт по триггерами на вход пользователя в систему, на подключение к отключенному сеансу, и на просто периодический запуск (у меня один раз в час). Задание выполняется только при наличии залогинившегося пользователя. Для отключения от шлюза при выходе пользователя используется стандартный скрипт (logoff script), т.к. в планировщике задач нет соответствующего триггера.
Примерный вид задания авторизации:



Так же в планах (но руки не дошли ещё) на выход пользователя повесить скрипт, отключающий эту задачу, т.к. иначе она каждый час пытается запуститься, но если пользователя нет в системе — пишет в историю ошибку. Хотя страшного ничего в этом нет, но перфекционизм, блин...

Спасибо всем, кто дочитал — надеюсь, этот пост сбережёт вам немного столь ценного нынче времени.




К сожалению, не доступен сервер mySQL