Безпека

Безпечний RDP: як закрити віддалений робочий стіл від інтернету

Зміст статті

Для адміністратора невеликої компанії, де бухгалтери працюють на сервері через віддалений робочий стіл. Після цих кроків порт 3389 буде закрито для сторонніх, облікові записи блокуватимуться після кількох невдалих спроб входу, а самі спроби буде видно в журналі.

Чому відкритий порт 3389 — проблема#

Сканери знаходять сервер із публічною адресою швидко, і паролі до RDP підбирають цілодобово. Навіть із надійними паролями це тисячі записів у журналі, заблоковані облікові записи бухгалтерів і ризик, що нову вразливість протоколу використають раніше, ніж ви встановите оновлення. Тому головне правило: порт 3389 не має бути відкритим для всього інтернету; решта налаштувань — другий рубіж захисту, а не заміна першого. Захист від DDoS, який входить до кожного нашого сервера, тут не допоможе: він фільтрує атаки мережевого рівня (L3/L4), а підбір паролів виглядає як звичайні підключення (докладніше).

Що знадобиться#

  • Windows Server 2025 або 2022 і обліковий запис із правами адміністратора. Усі команди — для Windows PowerShell, запущеної від імені адміністратора.
  • Перелік адрес, з яких працюють користувачі: статична публічна IP-адреса офісу або підмережа VPN. Якщо адреси динамічні (домашній чи мобільний інтернет), обмеження за адресами не підійде — потрібен VPN.
  • Запасний шлях до сервера на випадок помилки в правилі — віддалена консоль (за запитом через підтримку; на лінійці Лайт її немає). Домовтеся про неї до змін у брандмауері.
  • Свіжа резервна копія облікових баз.

Якщо сервер щойно видано, спершу пройдіть кроки першої години на Windows Server.

Крок 1 Закрийте порт 3389 від інтернету#

Варіанти — від найнадійнішого до найменш надійного.

Варіант А. RDP лише через VPN#

Найнадійніше: сервер приймає RDP тільки з адрес тунелю, а назовні відкрито лише порт VPN. WireGuard не відповідає на пакети без правильного ключа, тож сканер його не бачить. Як налаштувати тунель — у статті WireGuard: захищений канал між офісом і сервером. Після цього в правилі брандмауера (варіант Б) залиште тільки підмережу VPN, наприклад 10.66.0.0/24.

Варіант Б. Дозволити RDP лише з ваших адрес#

Вбудовані правила RDP зібрано в групі «Remote Desktop». У локалізованих системах назву групи перекладено, тому надійніше звертатися до правил за внутрішніми іменами: RemoteDesktop-UserMode-In-TCP, RemoteDesktop-UserMode-In-UDP, RemoteDesktop-Shadow-In-TCP. Подивіться, з яких адрес правила дозволяють підключення зараз і з якої адреси підключені ви самі:

Get-NetFirewallRule -Name 'RemoteDesktop-*' | Get-NetFirewallAddressFilter | Format-Table InstanceID, RemoteAddress
Get-NetTCPConnection -LocalPort 3389 -State Established | Format-Table RemoteAddress, RemotePort

Перша команда має показати ці правила (у щойно встановленій системі — з адресою Any); якщо список порожній, шукайте правило за портом (команда нижче).

Увага. Помилка в адресі відріже вас від сервера, зазвичай разом із поточним сеансом. Перед зміною переконайтеся, що ваша адреса з другої команди є у списку дозволених, і створіть завдання-страховку: через 15 хвилин воно знову відкриє правила для всіх адрес (Any). Якщо доступ утрачено, а страховки немає, правило виправляють через віддалену консоль тією самою командою з -RemoteAddress Any.

$action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-NoProfile -Command "Set-NetFirewallRule -Name RemoteDesktop-* -RemoteAddress Any"'
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(15)
Register-ScheduledTask -TaskName 'RDP-rollback' -Action $action -Trigger $trigger -User 'NT AUTHORITY\SYSTEM' -RunLevel Highest

Set-NetFirewallRule -Name 'RemoteDesktop-*' -RemoteAddress '203.0.113.10', '198.51.100.0/24'

Тут 203.0.113.10 — приклад адреси офісу, 198.51.100.0/24 — приклад підмережі; підставте свої (формати значень — у довідці Set-NetFirewallRule). Не закриваючи поточний сеанс, відкрийте ще одне підключення з дозволеної адреси. Якщо воно працює, видаліть страховку, інакше через 15 хвилин порт знову відкриється для всіх:

Unregister-ScheduledTask -TaskName 'RDP-rollback' -Confirm:$false

Перевірте також, чи немає інших дозвільних правил для того самого порту: вони діють незалежно від вбудованих.

Get-NetFirewallPortFilter -Protocol TCP | Where-Object { $_.LocalPort -eq '3389' } | Get-NetFirewallRule | Format-Table Name, DisplayName, Enabled, Action

Шлюз віддалених робочих столів#

Третій шлях — роль Remote Desktop Gateway: клієнти підключаються через HTTPS (порт 443), а сам RDP назовні не відкрито. Це окрема роль зі своїм сертифікатом і політиками; для кількох бухгалтерів VPN зазвичай простіший.

Зміна порту — не захист#

Перенесення RDP з 3389 на інший порт лише ненадовго зменшує шум у журналі: сканери перебирають усі порти й розпізнають RDP за відповіддю.

Крок 2 Обов’язкові налаштування на сервері#

Автентифікація на рівні мережі (NLA)#

З NLA сервер перевіряє ім’я користувача й пароль до створення сеансу; без неї будь-хто бачить екран входу. Перевірте:

Get-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication

Значення 1 — NLA обов’язкова. Якщо 0, увімкніть:

Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp' -Name UserAuthentication -Value 1

Те саме задає політика «Require user authentication for remote connections by using Network Level Authentication»: gpedit.msc → Computer Configuration → Administrative Templates → Windows Components → Remote Desktop Services → Remote Desktop Session Host → Security. Політика має перевагу над значенням у реєстрі.

Окремі користувачі та вбудований Administrator#

Кожен бухгалтер працює під власним обліковим записом без прав адміністратора; право входу через RDP дає група Remote Desktop Users. Групи в командах указано за SID, щоб команди працювали в будь-якій локалізації: S-1-5-32-555 — Remote Desktop Users, S-1-5-32-544 — Administrators.

$pw = Read-Host -AsSecureString -Prompt 'Password'
New-LocalUser -Name 'accountant1' -Password $pw -FullName 'Accountant 1'
Add-LocalGroupMember -SID 'S-1-5-32-555' -Member 'accountant1'

До імені Administrator паролі підбирають насамперед, тому створіть іншого адміністратора. Ім’я admin тут — приклад; оберіть таке, якого немає у словниках для підбору.

$pw = Read-Host -AsSecureString -Prompt 'Password'
New-LocalUser -Name 'admin' -Password $pw
Add-LocalGroupMember -SID 'S-1-5-32-544' -Member 'admin'

Увійдіть під новим адміністратором в окремому сеансі і лише після цього вимкніть вбудований обліковий запис (його SID закінчується на 500):

Get-LocalUser | Where-Object { $_.SID -like 'S-1-5-21-*-500' } | Disable-LocalUser

Замість вимкнення запис можна перейменувати командою Rename-LocalUser; увімкнути знову — Enable-LocalUser. Якщо від імені вбудованого запису працюють заплановані завдання чи резервне копіювання, спершу переведіть їх на інший запис.

Блокування облікових записів і паролі#

Поточні значення показує net accounts. За статтею Microsoft KB5020282, у системах, установлених з образу, який уже містить оновлення від 11 жовтня 2022 року (це Windows Server 2025 і нові образи Windows Server 2022), блокування ввімкнено одразу: 10 невдалих спроб за 10 хвилин блокують обліковий запис на 10 хвилин, зокрема й вбудований Administrator. У системах зі старіших образів поріг дорівнює 0, тобто блокування немає. Перевірте й за потреби задайте:

net accounts
net accounts /lockoutthreshold:10 /lockoutwindow:15 /lockoutduration:15
net accounts /minpwlen:12

Ті самі параметри — в secpol.msc → Account Policies → Account Lockout Policy; там само перевірте, що ввімкнено «Allow Administrator account lockout», а в Password Policy — «Password must meet complexity requirements». Блокування вбудованого адміністратора діє лише на мережевий вхід, з консолі увійти можна. Якщо сервер у домені, ці політики задає домен. Довжина пароля важить більше, ніж спецсимволи: фраза з кількох слів краща за коротке «складне» слово.

Оновлення, обмеження сеансів і переспрямування#

  • Оновлення. Встановлюйте щомісячні оновлення Windows (Settings → Windows Update або sconfig) і плануйте час на перезавантаження: саме вони закривають вразливості RDP.
  • Обмеження сеансів. У gpedit.msc, поруч із політикою NLA, є розділ Session Time Limits. «Set time limit for active but idle Remote Desktop Services sessions» від’єднує неактивний сеанс (наприклад, через 30–60 хвилин), «Set time limit for disconnected sessions» завершує від’єднаний (наприклад, через кілька годин). Завершення закриває програми без збереження, тож узгодьте значення з бухгалтерами.
  • Переспрямування. У розділі Device and Resource Redirection є «Do not allow drive redirection» і «Do not allow Clipboard redirection». Диски домашнього комп’ютера, підключені до сеансу, — це шлях для шкідливих програм на сервер і для даних із сервера назовні. Вирішіть свідомо: якщо файли через RDP не передають, вимкніть переспрямування дисків; буфер обміну лишайте, тільки якщо він потрібен для роботи.

Після зміни політик виконайте gpupdate /force; вони діють для нових підключень.

Як перевірити результат#

  1. З мережі, якої немає серед дозволених (наприклад, з мобільного інтернету), виконайте Test-NetConnection -ComputerName 203.0.113.50 -Port 3389 (адреса — приклад). Має бути TcpTestSucceeded : False, а з офісу чи через VPN — True.
  2. net accounts показує ненульовий поріг блокування, перевірка NLA повертає 1, а Get-LocalUser показує, що вбудований Administrator вимкнено.
  3. У журналі більше немає чужих спроб входу. Невдалий вхід — це подія 4625 у журналі Security:
$events = @(Get-WinEvent -FilterHashtable @{ LogName = 'Security'; Id = 4625; StartTime = (Get-Date).AddDays(-1) } -ErrorAction SilentlyContinue)
$events.Count
$events | Group-Object { $_.Properties[19].Value } | Sort-Object Count -Descending | Select-Object -First 10 Count, Name
$events | Group-Object { $_.Properties[5].Value } | Sort-Object Count -Descending | Select-Object -First 10 Count, Name

Перша таблиця — адреси джерел, друга — імена, до яких підбирали пароль. Сотні й тисячі записів за добу з чужих адрес означають, що порт досі відкритий; після кроку 1 мають лишитися тільки помилки ваших користувачів. Якщо подій немає зовсім, перевірте аудит невдалих входів і за потреби ввімкніть його:

auditpol /get /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}"
auditpol /set /subcategory:"{0CCE9215-69AE-11D9-BED3-505054503030}" /failure:enable

Типові помилки#

  • Обмежили правило за адресою, а в офісі динамічна IP-адреса: щойно вона зміниться, ніхто не зайде. Для динамічних адрес потрібен VPN.
  • Змінили вбудовані правила, але лишилося інше дозвільне правило для порту 3389 або брандмауер Windows вимкнено «на час налагодження». Не вимикайте його.
  • Увімкнули блокування, а порт лишили відкритим: сторонній, який знає імена користувачів, навмисно блокує бухгалтерів. Спершу — крок 1.
  • Усі бухгалтери працюють під одним обліковим записом або мають права адміністратора, «щоб програма оновлювалася».
  • Вимкнули NLA, бо старий клієнт не підключається. Оновіть клієнт, а не послаблюйте захист сервера.
  • Забули про термін дії паролів: типово це 42 дні (Maximum password age у net accounts), а з NLA прострочений пароль під час входу змінити не вдасться. Нагадуйте користувачам змінювати пароль заздалегідь (у сеансі — Ctrl+Alt+End).

Що далі#