Предприятие состоит из офиса и удаленных магазинов. Однажды работник увел базу клиентов на флешке. После этого все срочно перешли на удаленный рабочий стол с отключенным локальным интерфейсом. Но нужно еще больше контроля админам! Под катом описан способ немного повысить безопасность и контроль ситуации.
Сервер Windows Server 2012 R2 Standard.
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
<?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) <= 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/