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

Сервер 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%. Зато нечестные сотрудники будут вынуждены делать свои темные дела на рабочем месте, а это более опасно для них. Приятного использования!

Комментарии (26)


  1. 360apm
    14.09.2018 16:27
    +1

    Отличное чтиво на пятницу на вечер, люблю мусор в такое время ))

    Все это делалось предыдущим админом на скорую руку, поэтому сейчас вся инфраструктура стоит на костылях.

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

    :)

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

    А вышеописанное точно не городушки?


    1. DjSapsan Автор
      14.09.2018 16:39

      Предприятие работает больше 5 лет в трех городах и большую часть времени вообще без IT-шников. Точнее был один чувак из другого города, но он приезжал на точку, кидал провода через головы посреди офиса и уезжал. За это время без контроля вся инфраструктура превратилась в раковую опухоль, исправить что-то не поломав систему невозможно. Если есть конкретное замечание по скрипту — пожалуйста, я жду. А обсуждать «городушки» не нужно.


  1. osipov_dv
    14.09.2018 16:35
    +1

    Открываем мануал по RDGW и перестаем изобретать велосипед…


    1. DjSapsan Автор
      14.09.2018 16:44

      Я перерыл всё в поисках ограничений пользователей. IP в черный список — пожалуйста, но вот пользователей не так просто.


      1. osipov_dv
        14.09.2018 17:05

        не нужно привязываться к ip, проверяйте членство в группах компьютеров откуда идёт подключение и пользователей. надо сделать политику на устройство с проверкой на членство в группе АД и пользователей определённой группы. и вторую политику без проверки устройства, но с проверкой группы пользователей 2. тогда первые будут ходить только с доменных машин, а вторые отовсюду. но я опрометчиво посчитал что у вас есть АД и сервер на хостинге в домене. Если нет, то я не прав, но костыль ваш тоже не очень… тогда можно смотреть авторизацию по сертификатам. в шедулере сейчас есть дыра с повышением прав, ваш костыль просто подарок.


        1. DjSapsan Автор
          14.09.2018 17:19

          Домена нет, сертификаты игнорируем, разные группы на каждой рабочей станции. Такой зоопарк.


          1. igrblkv
            14.09.2018 22:26

            Может первым пунктом следует причесать зоопарк насколько возможно? Домен поднять? VPN организовать? А если пользователь подключился к ВПН — то он и с ресурсами «локалки» может полноценно работать, например?
            Потом и удаленно админить будет легче…

            Я, конечно, понимаю, что все зависит от руководства — сам пришел в контору с одним б/у сервером, без ИБП, с RAID0 из шести дисков (т.е. три RAID0-тома по два диска в каждом) и без бэкапов (на тот-же RAID0-том, ведь не считается?). «Да у нас шесть лет уже всё работает, какой ИБП, мы сервер на Авито дешевле купили, чем этот ИБП?» Но диск умер, денек бухгалтерия со всеми покуковала — и всё сразу сдвинулось с мертвой точки…


  1. berez
    14.09.2018 16:38
    +2

    «Запретить определенным пользователям заходить только с разрешенного IP» — очень двойственная фраза.
    Может означать оно из двух:
    1. запретить пользователю заходить с оставшихся разрешенными IP (т.е. заблокировать его нахрен вообще), или
    2. Больше не проверять, разрешен IP или нет (т.е. пускать отовсюду).

    В любом случае — душевное название, душевное…


    1. DjSapsan Автор
      14.09.2018 16:42

      Переписал одну половину, но оставил другую. На работоспособность не влияет.


      1. berez
        14.09.2018 17:03

        На работоспособность не влияет.

        Работоспособность — это прекрасно. Но важнее все-таки, когда админ понимает, что именно делает скрипт. Для понимания очень важны точные описания.

        Допустим, вас переманили в фирму «Рога и Копыта плюс». Вместо вас пришел юный падаван с желанием во всем разобраться. Открывает он список задач и видит ваше «запретить заходить с разрешенных». Поймет ли он, для чего нужна эта задача, или ему надо будет в скрипт смотреть? :)

        Впрочем, ситуация не ограничивается приходом нового админа. Вы сами вполне можете забыть про всю эту машинерию на пару лет (работает и прекрасно). Но вот — вдруг — что-то где-то поломалось, юзер не может зайти, надо срочно фиксить, все вокруг бегают с криками «давай-давай!», а начальство тяжело дышит из-за плеча. Сможете ли вы быстро и безошибочно разобраться в полузабытых скриптах и задачах, особенно если за годы их много накопилось?


        1. DjSapsan Автор
          14.09.2018 17:14

          Всё верно, но на момент написание вообще не было времени что-либо перечитывать. Так что спасибо за замечание, буду исправлять.


  1. Evgenym
    14.09.2018 16:40

    Может, лучше разобраться с файерволлом? Сервак, торчащий голой задницей RDP в интернет — не очень безопасно изначально.


    1. DjSapsan Автор
      14.09.2018 16:51

      На сервак заходят с разных городов и с домов. Публичный IP обязателен. В данный момент работаю над переводом внеофисных точек работу без RDP.


      1. Andrusha
        14.09.2018 16:53

        Я так понимаю, вариант организовать VPN для этого не рассматривался?


        1. DjSapsan Автор
          14.09.2018 16:57

          VPN для офиса уже настроен, магазины пока нет. Как изначально рассматривалось уже никто не знает. После воровства срочно нужно было всем запретить доступ к локальным компам.


      1. harlong
        15.09.2018 01:47

        А хотя бы «завернуть» его в SSH с туннелированием портов? Иначе через пару месяцев вас удивят логи файрвола по порту 3389, а еще через годик-другой может очень удивить потеря/шифрование критичных данных с требованием выкупа.


  1. 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 запускайте. Лучше не использовать рабочие учетки для запуска задач — либо делать специальные служебные, либо пользоваться встроенными.


    1. DjSapsan Автор
      14.09.2018 17:20

      Спасибо, возьму на заметку.


  1. nukler
    14.09.2018 17:14

    Я дико извиняюсь, простите. Но что такое разрешенный IP?
    Пул IP? Какой он? Вот у меня к примеру дома пул IP это 10.0.0.0/8 (от так мне удобно в жизни).
    Если он совпадет с тем что Вы разрешили?

    Есть мнение что все же лучше VPN (тот же PPTP, кривой косой, но лучше чем никто)


    1. DjSapsan Автор
      14.09.2018 17:17

      Офис имеет постоянный белый IP. Изнутри офиса менеджеры могут заходить. С любого другого адреса — нельзя. Сервер облачный, если что.


      1. nukler
        14.09.2018 17:19

        Я это и имел в виду, то есть у Вас есть пул IP который разрешен, к примеру 192.168.100.0/24 если у меня дома такой же пул и я работаю у Вас в компании то в теории я из дома могу зайти?

        P.S. Сори, понял, Вы чекаете белый статический IP. Гм, тогда как из дома то работать? Ручками пишете IP нужных людей?


        1. DjSapsan Автор
          14.09.2018 17:41

          Читайте статью. Скрипт затрагивает конкретных пользователей. Остальныe могут работать с дому или в командировкe


          1. pnetmon
            15.09.2018 10:39

            Читать статью конечно можно. Но только из комментариев становится понятно что скрипт применяется только к конкретным пользователям. Эти пользователи могут подключаться только с белого IP офиса. Ко всем остальным — удаленным пользователям и магазинам он не применяется.


            Вот вначале это Одна из новых задач — на облачный рабочий стол офисным менеджерам можно заходить только с офиса. Дома нельзя. При этом оставить избранным возможность работать из дому. А удаленные магазины вообще не трогать. по привычке читается что скрипт для избранных менеджеров работающих с белых IP.


            После воровства срочно нужно было всем запретить доступ к локальным компам.

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


  1. DjSapsan Автор
    14.09.2018 17:34

    192.168.100.0/24 это серый адрес. При выходе в интернет используется публичный. У вас дома публичный адрес отличается от нашего, так что не зайдете.


  1. rtzra
    15.09.2018 11:24

    Знатный велосипед, однако.
    Сделайте хотя бы VPN между офисом и магазинами, на базе Mikrotik получится довольно недорого и безопасно (например L2TP + IPSec). Поднимите Active Directory и всех пользователей туда — получите единое пространство для авторизации и управление правами/доступами). Если требуется подключение извне (всегда есть какие-нибудь путешествующие менеджеры), настройте RDGW и опубликуйте приложения. Если так уж надо выставить в интернет RDP — можно использовать EvlWatcher для блокировки ботов.


  1. tenhi_shadow
    15.09.2018 20:44

    Я думаю, что если стоит задача разрешить какой-то порт(3389) на доступ с определённых IP это прежде всего задача сетевая, которая должна решаться на сетевом оборудовании, а не скриптами на винде(ну… странный выбор)

    Глобально правильнее(на мой взгяд) сделать офис, магазины, облако в одном пространстве сети ( к примеру, с помощью GRE+IPSEC+OSPF). Далее уже через ACL нарулить чё-куда-кому.
    Для мигрирующих менеджеров точно таким же образом организовать vpn(к примеру Openvpn), с резервированными адресами и опять же, списком доступа.