PowerShell · 27.03.2026

Неявные границы

Аттеншн, граждане! Некропост детектед!

Время для вечернего пятничного скрипта с щепоткой магии для реестра серверной операционной системы Windows Server. Все эксперименты во время написания сабжа проводились на Windows Server 2012 R2. Велика вероятность, что метод сработает и на более поздних версиях системы, но ошибку, описанную в данном посте, я встречал лишь раз. Экспериментировать дальше смысла никакого не было.

Началось всё с того, что моё внимание обратили на весьма странные значения графика TCP-подключений в мониторе ресурсов системы одного из серверов:

Из представленных данных видно, что на данный момент количество TCP-подключений ограничено 10 единицами и все они заняты. Решил опросить систему на предмет соединений с помощью командлета:

Get-NetTCPConnection | Measure-Object

Get-NetTCPConnection выдал совершенно другие цифры:

Конечно, совершенно непонятно, что конкретно подразумевается под количеством TCP-подключений с точки зрения командлета Get-NetTCPConnection и монитора ресурсов соответственно. Быть может, они оба правы, просто видят ситуацию с разных уровней абстракции.

В данном случае, единственная вещь в системе, которая может пролить свет на ситуацию — это реестр. Двигаемся в раздел:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

Любопытно, что в данном разделе присутствовали параметры MaxUserPort и TimeWaitDelay, которых, казалось бы, достаточно для полноценной работы TCP. Не хватало только параметра EnableConnectionRateLimiting.

Добавляю в указанный раздел упомянутый параметр со значением 0:

Сервер перезапускался в ручном режиме в ночное время, поэтому результат проделанной работы я получил только спустя половину суток.

После перезапуска на следующее утро монитор ресурсов радостно сообщил:

На случай, если данная проблема встретится где-то ещё — я решил написать скрипт для занесения всех необходимых параметров в реестр:

# Заголовок скрипта #
[System.Console]::Title = "Снятие ограничения подключений TCP"

# Определяем путь к ключу реестра #
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"

# Проверяем существование ключа #
if (-not (Test-Path $regPath)) 
{
    Write-Host -ForegroundColor Red "Ключ реестра не существует: $regPath"
    exit 1
}

# Добавляем параметр MaxUserPort #
$maxUserPortName = "MaxUserPort"
$maxUserPortValue = [uint32]65534
Set-ItemProperty -Path $regPath -Name $maxUserPortName -Value $maxUserPortValue -Type DWord
Write-Host -ForegroundColor Green "Параметр $maxUserPortName с значением $maxUserPortValue добавлен."

# Добавляем параметр EnableConnectionRateLimiting #
$enableConnectionRateLimitingName = "EnableConnectionRateLimiting"
$enableConnectionRateLimitingValue = [uint32]0
Set-ItemProperty -Path $regPath -Name $enableConnectionRateLimitingName -Value $enableConnectionRateLimitingValue -Type DWord
Write-Host -ForegroundColor Green "Параметр $enableConnectionRateLimitingName с значением $enableConnectionRateLimitingValue добавлен."

# Добавляем параметр TimeWaitDelay #
$timeWaitDelayName = "TimeWaitDelay"
$timeWaitDelayValue = [uint32]30
Set-ItemProperty -Path $regPath -Name $timeWaitDelayName -Value $timeWaitDelayValue -Type DWord
Write-Host -ForegroundColor Green "Параметр $timeWaitDelayName с значением $timeWaitDelayValue добавлен."

# Работа скрипта завершена #
Write-Host
Write-Host -ForegroundColor Yellow "Все параметры успешно добавлены в реестр."
Write-Host -ForegroundColor Yellow "Нажмите на любую кнопку для выхода..."
Read-Host

Думаю, основная логика работы скрипта понятна. Умышленно не стал добавлять обработчик ошибок, ограничился только методом выхода из скрипта с кодом 1, на тот редкий случай если ветка реестра по какой-то причине не будет найдена.