Предприятие состоит из офиса и удаленных магазинов. Однажды работник увел базу клиентов на флешке. После этого все срочно перешли на удаленный рабочий стол с отключенным локальным интерфейсом. Но нужно еще больше контроля админам! Под катом описан способ немного повысить безопасность и контроль ситуации.
Сервер 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 на системное имя пользователя, которого нужно ограничить.
После создание таска появляется окно:
Триггеры запуска:
- При удаленном подключении к пользовательскому сеансу username
- При входе username
Действие: запуск программы PowerShell с аргументом -File «C:\SCRIPTFOLDER\Scripts\kickUsername.ps1»
Обязательно выполнять от админа с наивысшими правами. Нажимаем ОК, вводим пароль админа. Задача готова! Теперь при попытке подключения ограниченного пользователя с чужих IP-адресов его будет выкидывать, а нам будет писать лог в папочку со скриптами.
Для ограничения нового юзера нужно повторить процесс (хотел сделать список запретов в файлике, но не хватает опыта и времени). На этом всё.
Критика очень приветствуется, т.к. это мой первый код на PowersHell. Также я осознаю, что данный способ не защищает ценную информацию на 100%. Зато нечестные сотрудники будут вынуждены делать свои темные дела на рабочем месте, а это более опасно для них. Приятного использования!
Комментарии (26)
osipov_dv
14.09.2018 16:35+1Открываем мануал по RDGW и перестаем изобретать велосипед…
DjSapsan Автор
14.09.2018 16:44Я перерыл всё в поисках ограничений пользователей. IP в черный список — пожалуйста, но вот пользователей не так просто.
osipov_dv
14.09.2018 17:05не нужно привязываться к ip, проверяйте членство в группах компьютеров откуда идёт подключение и пользователей. надо сделать политику на устройство с проверкой на членство в группе АД и пользователей определённой группы. и вторую политику без проверки устройства, но с проверкой группы пользователей 2. тогда первые будут ходить только с доменных машин, а вторые отовсюду. но я опрометчиво посчитал что у вас есть АД и сервер на хостинге в домене. Если нет, то я не прав, но костыль ваш тоже не очень… тогда можно смотреть авторизацию по сертификатам. в шедулере сейчас есть дыра с повышением прав, ваш костыль просто подарок.
DjSapsan Автор
14.09.2018 17:19Домена нет, сертификаты игнорируем, разные группы на каждой рабочей станции. Такой зоопарк.
igrblkv
14.09.2018 22:26Может первым пунктом следует причесать зоопарк насколько возможно? Домен поднять? VPN организовать? А если пользователь подключился к ВПН — то он и с ресурсами «локалки» может полноценно работать, например?
Потом и удаленно админить будет легче…
Я, конечно, понимаю, что все зависит от руководства — сам пришел в контору с одним б/у сервером, без ИБП, с RAID0 из шести дисков (т.е. три RAID0-тома по два диска в каждом) и без бэкапов (на тот-же RAID0-том, ведь не считается?). «Да у нас шесть лет уже всё работает, какой ИБП, мы сервер на Авито дешевле купили, чем этот ИБП?» Но диск умер, денек бухгалтерия со всеми покуковала — и всё сразу сдвинулось с мертвой точки…
berez
14.09.2018 16:38+2«Запретить определенным пользователям заходить только с разрешенного IP» — очень двойственная фраза.
Может означать оно из двух:
1. запретить пользователю заходить с оставшихся разрешенными IP (т.е. заблокировать его нахрен вообще), или
2. Больше не проверять, разрешен IP или нет (т.е. пускать отовсюду).
В любом случае — душевное название, душевное…DjSapsan Автор
14.09.2018 16:42Переписал одну половину, но оставил другую. На работоспособность не влияет.
berez
14.09.2018 17:03На работоспособность не влияет.
Работоспособность — это прекрасно. Но важнее все-таки, когда админ понимает, что именно делает скрипт. Для понимания очень важны точные описания.
Допустим, вас переманили в фирму «Рога и Копыта плюс». Вместо вас пришел юный падаван с желанием во всем разобраться. Открывает он список задач и видит ваше «запретить заходить с разрешенных». Поймет ли он, для чего нужна эта задача, или ему надо будет в скрипт смотреть? :)
Впрочем, ситуация не ограничивается приходом нового админа. Вы сами вполне можете забыть про всю эту машинерию на пару лет (работает и прекрасно). Но вот — вдруг — что-то где-то поломалось, юзер не может зайти, надо срочно фиксить, все вокруг бегают с криками «давай-давай!», а начальство тяжело дышит из-за плеча. Сможете ли вы быстро и безошибочно разобраться в полузабытых скриптах и задачах, особенно если за годы их много накопилось?DjSapsan Автор
14.09.2018 17:14Всё верно, но на момент написание вообще не было времени что-либо перечитывать. Так что спасибо за замечание, буду исправлять.
Evgenym
14.09.2018 16:40Может, лучше разобраться с файерволлом? Сервак, торчащий
голой задницейRDP в интернет — не очень безопасно изначально.DjSapsan Автор
14.09.2018 16:51На сервак заходят с разных городов и с домов. Публичный IP обязателен. В данный момент работаю над переводом внеофисных точек работу без RDP.
harlong
15.09.2018 01:47А хотя бы «завернуть» его в SSH с туннелированием портов? Иначе через пару месяцев вас удивят логи файрвола по порту 3389, а еще через годик-другой может очень удивить потеря/шифрование критичных данных с требованием выкупа.
ildarz
14.09.2018 17:00Как уже заметили, неверен сам подход, но, если уж хотите только по скрипту, то пожалуйста.
1. У вас триггер на определенное событие, но в скрипте вы почему-то проверяете не его, а последнее похожее (они совершенно не обязательно совпадут). Ссылайтесь сразу непосредственно на правильное событие, как-то так — blogs.technet.microsoft.com/wincat/2011/08/25/trigger-a-powershell-script-from-a-windows-event
2. Парсить message — не очень хорошая идея в плане переносимости и поддерживаемости скрипта. Лучше брать непосредственно нужные поля из события.
3. Если используете не командлеты PS, а вызовы внешних команд, лучше это делать через вызов cmd /c «command [parameter]… » — избежите разных интересных проблем (совпадение алиаса командлета с именем внешней команды, неверную обработку параметров, и т.п.).
4. «Обязательно выполнять от админа с наивысшими правами. » — от SYSTEM запускайте. Лучше не использовать рабочие учетки для запуска задач — либо делать специальные служебные, либо пользоваться встроенными.
nukler
14.09.2018 17:14Я дико извиняюсь, простите. Но что такое разрешенный IP?
Пул IP? Какой он? Вот у меня к примеру дома пул IP это 10.0.0.0/8 (от так мне удобно в жизни).
Если он совпадет с тем что Вы разрешили?
Есть мнение что все же лучше VPN (тот же PPTP, кривой косой, но лучше чем никто)DjSapsan Автор
14.09.2018 17:17Офис имеет постоянный белый IP. Изнутри офиса менеджеры могут заходить. С любого другого адреса — нельзя. Сервер облачный, если что.
nukler
14.09.2018 17:19Я это и имел в виду, то есть у Вас есть пул IP который разрешен, к примеру 192.168.100.0/24 если у меня дома такой же пул и я работаю у Вас в компании то в теории я из дома могу зайти?
P.S. Сори, понял, Вы чекаете белый статический IP. Гм, тогда как из дома то работать? Ручками пишете IP нужных людей?DjSapsan Автор
14.09.2018 17:41Читайте статью. Скрипт затрагивает конкретных пользователей. Остальныe могут работать с дому или в командировкe
pnetmon
15.09.2018 10:39Читать статью конечно можно. Но только из комментариев становится понятно что скрипт применяется только к конкретным пользователям. Эти пользователи могут подключаться только с белого IP офиса. Ко всем остальным — удаленным пользователям и магазинам он не применяется.
Вот вначале это Одна из новых задач — на облачный рабочий стол офисным менеджерам можно заходить только с офиса. Дома нельзя. При этом оставить избранным возможность работать из дому. А удаленные магазины вообще не трогать. по привычке читается что скрипт для избранных менеджеров работающих с белых IP.
После воровства срочно нужно было всем запретить доступ к локальным компам.
Это конечно красиво только с офисной сети. Но программы типа teamviewera легко организуют удаленный доступ к офисному компьютеру для совершения действий в темную (даже например выключен монитор), или подключение с левых устройств в офисной сети которая не контролируется.
DjSapsan Автор
14.09.2018 17:34192.168.100.0/24 это серый адрес. При выходе в интернет используется публичный. У вас дома публичный адрес отличается от нашего, так что не зайдете.
rtzra
15.09.2018 11:24Знатный велосипед, однако.
Сделайте хотя бы VPN между офисом и магазинами, на базе Mikrotik получится довольно недорого и безопасно (например L2TP + IPSec). Поднимите Active Directory и всех пользователей туда — получите единое пространство для авторизации и управление правами/доступами). Если требуется подключение извне (всегда есть какие-нибудь путешествующие менеджеры), настройте RDGW и опубликуйте приложения. Если так уж надо выставить в интернет RDP — можно использовать EvlWatcher для блокировки ботов.
tenhi_shadow
15.09.2018 20:44Я думаю, что если стоит задача разрешить какой-то порт(3389) на доступ с определённых IP это прежде всего задача сетевая, которая должна решаться на сетевом оборудовании, а не скриптами на винде(ну… странный выбор)
Глобально правильнее(на мой взгяд) сделать офис, магазины, облако в одном пространстве сети ( к примеру, с помощью GRE+IPSEC+OSPF). Далее уже через ACL нарулить чё-куда-кому.
Для мигрирующих менеджеров точно таким же образом организовать vpn(к примеру Openvpn), с резервированными адресами и опять же, списком доступа.
360apm
Отличное чтиво на пятницу на вечер, люблю мусор в такое время ))
а ещё всегда в очереди перед банкоматом тупой, слева на дороге лихач и соседи всегда мешают
+
:)
А точно не бизнес решает, что внедрять, а что нет, какие риски и т.д.? А то предыдущий гореадмин городушек нагородил, а всем теперь расхлебывать
А вышеописанное точно не городушки?
DjSapsan Автор
Предприятие работает больше 5 лет в трех городах и большую часть времени вообще без IT-шников. Точнее был один чувак из другого города, но он приезжал на точку, кидал провода через головы посреди офиса и уезжал. За это время без контроля вся инфраструктура превратилась в раковую опухоль, исправить что-то не поломав систему невозможно. Если есть конкретное замечание по скрипту — пожалуйста, я жду. А обсуждать «городушки» не нужно.