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




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

Сервер 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
    /#19111149 / +1

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

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

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

    :)

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

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

    • DjSapsan
      /#19111209

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

  2. osipov_dv
    /#19111185 / +1

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

    • DjSapsan
      /#19111241

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

      • osipov_dv
        /#19111351

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

        • DjSapsan
          /#19111433

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

          • igrblkv
            /#19112445

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

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

  3. berez
    /#19111195 / +2

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

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

    • DjSapsan
      /#19111229

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

      • berez
        /#19111341

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

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

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

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

        • DjSapsan
          /#19111409

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

  4. Evgenym
    /#19111213

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

    • DjSapsan
      /#19111275

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

      • Andrusha
        /#19111293

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

        • DjSapsan
          /#19111317

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

      • harlong
        /#19112881

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

  5. ildarz
    /#19111329

    Как уже заметили, неверен сам подход, но, если уж хотите только по скрипту, то пожалуйста.

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

    • DjSapsan
      /#19111441

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

  6. nukler
    /#19111407

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

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

    • DjSapsan
      /#19111417

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

      • nukler
        /#19111435

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

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

        • DjSapsan
          /#19111555

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

          • pnetmon
            /#19113421

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


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


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

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

  7. DjSapsan
    /#19111527

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

  8. rtzra
    /#19113521

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

  9. tenhi_shadow
    /#19114843

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

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