Избирательный запрет IP на облачный Windows Server 2012 через RDP


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

Сервер Windows Server 2012 R2 Standard.

PowerShell версия

PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.42000
BuildVersion 6.3.9600.18773
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2

Все это делалось предыдущим админом на скорую руку, поэтому сейчас вся инфраструктура стоит на костылях. Затем я пришел всё это поддерживать. Одна из новых задач — на облачный рабочий стол офисным менеджерам можно заходить только с офиса. Дома нельзя. При этом оставить избранным возможность работать из дому. А удаленные магазины вообще не трогать. Обычно это делается через политики фаервола или через домен. Так как блокировка нужна избирательная, домена нет, а сервер облачный, то пришлось искать необычные решения.
Я никогда не писал в PowerShell, поэтому сделал платный запрос техникам нашего хостинга. Но пока они соображали, я набросал быстрое и рабочее решение. Вот схема:

Создаем папочку для скриптов. Добавляем сам скрипт:

#saved as UTF8 # $username = "username"			# Системное имя пользователя $localnet = "1.2.3.4"	# Разрешенный IP  $lastevent = Get-EventLog Security -Message "*$username*адрес:*.*.*.*" -Newest 1	# Последнее удачное событие входа $IP = $lastevent.message.substring($lastevent.message.indexof("Сетевой адрес:")+15,$lastevent.message.indexof("Порт:")-$lastevent.message.indexof("Сетевой адрес:")-18) $IDbyName = ((query session $username)[1] -split '\s+')[3]							# Вытягиваем адрес "обрезанием" события  if ($IDbyName -notlike $null) {if ($IP -notlike $localnet) {						# Проверка и выбрасывание 	logoff $IDbyName 	"`n---------" | Out-File "C:\SCRIPTFOLDER\Scripts\log.txt" -Append 	Get-Date | Out-File "C:\SCRIPTFOLDER\Scripts\log.txt" -Append 	"Сессия RDP завершена`nUSER: $username `nIP: $ip" | Out-File "C:\SCRIPTFOLDER\Scripts\log.txt" -Append }}

Скрипт не самый гибкий, но работающий на ура. Теперь об автоматизации. Заходим в планировщик заданий. Создаем вручную событие, а лучше импортировать через этот task.xml

task.xml

<?xml version="1.0" encoding="UTF-16"?> <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">   <RegistrationInfo>     <Date>2018-08-09T15:44:22.8651577</Date>     <Author>ServerName\AdminUser</Author>     <Description>Запретить определенным пользователям заходить только с разрешенного IP</Description>   </RegistrationInfo>   <Triggers>     <EventTrigger>       <Enabled>false</Enabled>       <Subscription><QueryList><Query Id="0" Path="Security"><Select Path="Security">*[System[(Level=4 or Level=0) and (band(Keywords,9007199254740992)) and (EventID=4648) and TimeCreated[timediff(@SystemTime) &lt;= 3600000]]]</Select></Query></QueryList></Subscription>     </EventTrigger>     <SessionStateChangeTrigger>       <Enabled>true</Enabled>       <StateChange>RemoteConnect</StateChange>       <UserId>ServerName\username</UserId>     </SessionStateChangeTrigger>     <LogonTrigger>       <Enabled>true</Enabled>       <UserId>ServerName\username</UserId>     </LogonTrigger>   </Triggers>   <Principals>     <Principal id="Author">       <UserId>ServerName\AdminUser</UserId>       <LogonType>Password</LogonType>       <RunLevel>HighestAvailable</RunLevel>     </Principal>   </Principals>   <Settings>     <MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy>     <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>     <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>     <AllowHardTerminate>true</AllowHardTerminate>     <StartWhenAvailable>false</StartWhenAvailable>     <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>     <IdleSettings>       <StopOnIdleEnd>true</StopOnIdleEnd>       <RestartOnIdle>false</RestartOnIdle>     </IdleSettings>     <AllowStartOnDemand>true</AllowStartOnDemand>     <Enabled>false</Enabled>     <Hidden>false</Hidden>     <RunOnlyIfIdle>false</RunOnlyIfIdle>     <WakeToRun>false</WakeToRun>     <ExecutionTimeLimit>PT1H</ExecutionTimeLimit>     <Priority>7</Priority>     <RestartOnFailure>       <Interval>PT1M</Interval>       <Count>3</Count>     </RestartOnFailure>   </Settings>   <Actions Context="Author">     <Exec>       <Command>PowerShell</Command>       <Arguments>-File "C:\SCRIPTFOLDER\Scripts\kickUsername.ps1"</Arguments>     </Exec>   </Actions> </Task>

Не забудьте переправить ServerName на системное имя сервака, AdminUser на системное имя исполняющего админа и username на системное имя пользователя, которого нужно ограничить.
После создание таска появляется окно

Триггеры запуска:
1) При удаленном подключении к пользовательскому сеансу username
2) При входе username
Действие: запуск программы PowerShell с аргументом -File «C:\SCRIPTFOLDER\Scripts\kickUsername.ps1»
Обязательно выполнять от админа с наивысшими правами. Нажимаем ОК, вводим пароль админа. Задача готова! Теперь при попытке подключения ограниченного пользователя с чужих IP-адресов его будет выкидывать, а нам будет писать лог в папочку со скриптами.
Для ограничения нового юзера нужно повторить процесс (хотел сделать список запретов в файлике, но не хватает опыта и времени). На этом всё.
Критика очень приветствуется, т.к. это мой первый код на PowersHell. Также я осознаю, что данный способ не защищает ценную информацию на 100%. Зато нечестные сотрудники будут вынуждены делать свои темные дела на рабочем месте, а это более опасно для них. Приятного использования!


ссылка на оригинал статьи https://habr.com/post/423301/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *