Error de RDP: desbloquear una cuenta de Windows bloqueada (PowerShell)
Una cuenta de Windows bloqueada al iniciar sesión por RDP suele ser consecuencia de ataques automatizados. Este script de PowerShell desbloquea la cuenta, muestra las IP de origen y ajusta la directiva de bloqueo.
Tu inicio de sesión por Escritorio remoto falla de repente y Windows muestra un mensaje de este tipo: "Por motivos de seguridad se ha bloqueado la cuenta de usuario, ya que se han realizado demasiados intentos de inicio de sesión o de cambio de contraseña." Entonces la cuenta ha activado la directiva de bloqueo de cuentas de Windows. La causa es casi siempre la misma: alguien o algo está bombardeando tu acceso RDP con intentos de inicio de sesión desde Internet.
En esta guía te mostramos cómo desbloquear la cuenta, averiguar qué direcciones IP provocan los bloqueos y ajustar o desactivar la directiva de bloqueo. Todo eso lo resuelve un único script de PowerShell, sin tener que dar ni un clic en el editor de directivas de grupo.
¿Por qué se bloquea una cuenta de Windows al iniciar sesión por RDP?
Windows cuenta los intentos de inicio de sesión fallidos y bloquea la cuenta en cuanto se alcanza el umbral configurado. Esta protección tiene sentido, pero se convierte en un problema en cuanto el puerto RDP queda abierto a Internet: los bots automatizados prueban contraseñas las 24 horas del día y acaban bloqueando justo la cuenta con la que tú quieres trabajar.
Tres valores determinan este comportamiento:
- Umbral de bloqueo: número de intentos fallidos hasta que se bloquea la cuenta
- Duración del bloqueo: minutos que la cuenta permanece bloqueada
- Ventana de observación: minutos durante los cuales se suman los intentos fallidos
Abrir PowerShell como administrador
Abre Windows PowerShell como administrador. Para ello, haz clic con el botón derecho sobre "Windows PowerShell" en el menú Inicio y elige "Ejecutar como administrador". Sin permisos elevados, el script no puede desbloquear la cuenta ni modificar la directiva.
El script: desbloquear la cuenta y destapar a los atacantes
Ajusta el nombre de la cuenta y los valores que quieras en la sección "Configuración" y pega después el script en PowerShell:
#Requires -RunAsAdministrator
# KernelHost: desbloquear una cuenta RDP de Windows bloqueada y encontrar la causa
# Ejecutar en Windows PowerShell como administrador.
# ----------------------------------------------------------------------------
# Configuración: adáptala a tu entorno
# ----------------------------------------------------------------------------
$Username = 'Administrator' # la cuenta local que se debe desbloquear
$ApplyPolicy = $true # $false si la directiva de bloqueo debe quedar sin cambios
$LockoutThreshold = 10 # intentos fallidos hasta el bloqueo (0 = DESACTIVAR el bloqueo)
$LockoutDuration = 15 # minutos que la cuenta permanece bloqueada
$LockoutWindow = 15 # minutos durante los cuales se cuentan los intentos fallidos
# ----------------------------------------------------------------------------
# 1) Mostrar la directiva de bloqueo actual
Write-Host "`n=== 1) Directiva de bloqueo actual ===" -ForegroundColor Cyan
net accounts | Select-String 'Lockout|Sperr'
# 2) Desbloquear la cuenta
Write-Host "`n=== 2) Desbloquear la cuenta '$Username' ===" -ForegroundColor Cyan
try {
$user = [ADSI]"WinNT://$env:COMPUTERNAME/$Username,user"
if ($user.InvokeGet('IsAccountLocked')) {
$user.InvokeSet('IsAccountLocked', $false)
$user.SetInfo()
Write-Host " '$Username' estaba bloqueada y ahora está DESBLOQUEADA." -ForegroundColor Green
} else {
Write-Host " '$Username' no está bloqueada." -ForegroundColor Yellow
}
} catch {
Write-Warning " No se ha podido desbloquear '$Username': $($_.Exception.Message)"
}
# 3) Opcional: ajustar o desactivar la directiva de bloqueo
if ($ApplyPolicy) {
Write-Host "`n=== 3) Aplicar la directiva de bloqueo ===" -ForegroundColor Cyan
if ($LockoutThreshold -eq 0) {
net accounts /lockoutthreshold:0 | Out-Null
Write-Host " Bloqueo de cuentas DESACTIVADO (umbral 0)." -ForegroundColor Yellow
Write-Warning " En un servidor accesible desde Internet esto NO es recomendable."
} else {
net accounts /lockoutthreshold:$LockoutThreshold /lockoutduration:$LockoutDuration /lockoutwindow:$LockoutWindow | Out-Null
Write-Host " Umbral=$LockoutThreshold Duración=$LockoutDuration min Ventana=$LockoutWindow min" -ForegroundColor Green
}
}
# 4) ¿Quién provoca los bloqueos? (origen de los ataques RDP)
Write-Host "`n=== 4a) Últimos eventos de bloqueo (Security-ID 4740) ===" -ForegroundColor Cyan
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740} -MaxEvents 10 -ErrorAction SilentlyContinue |
ForEach-Object {
$x = [xml]$_.ToXml()
[pscustomobject]@{
Hora = $_.TimeCreated
CuentaBloqueada = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetUserName' }).'#text'
Origen = ($x.Event.EventData.Data | Where-Object { $_.Name -eq 'TargetDomainName' }).'#text'
}
} | Format-Table -AutoSize
Write-Host "=== 4b) IPs de origen más frecuentes de inicios de sesión fallidos, últimas 24 h (Security-ID 4625) ===" -ForegroundColor Cyan
$since = (Get-Date).AddHours(-24)
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=$since} -ErrorAction SilentlyContinue |
ForEach-Object {
([xml]$_.ToXml()).Event.EventData.Data |
Where-Object { $_.Name -eq 'IpAddress' } | Select-Object -ExpandProperty '#text'
} |
Where-Object { $_ -and $_ -ne '-' } |
Group-Object | Sort-Object Count -Descending | Select-Object -First 10 |
Format-Table Count, @{N='IPOrigen'; E={$_.Name}} -AutoSize
Qué hace el script paso a paso
- Muestra con
net accountsla directiva de bloqueo de cuentas actual, es decir, el umbral, la duración del bloqueo y la ventana de observación. - Desbloquea la cuenta indicada en
$Usernamea través del proveedor de directorio WinNT. Es el equivalente deUnlock-ADAccountpara cuentas locales. - Ajusta la directiva, siempre que
$ApplyPolicyesté en$true. Con los valores predeterminados el bloqueo se vuelve menos agresivo, y con$LockoutThreshold = 0lo desactivas por completo. - Lista los últimos eventos de bloqueo (ID de evento 4740) y las direcciones IP de origen más frecuentes de los inicios de sesión fallidos de las últimas 24 horas (ID de evento 4625). Esas son las direcciones desde las que se ataca tu acceso RDP.
Nota sobre el idioma: en un Windows en alemán, net accounts muestra los valores con etiquetas traducidas. Por eso el script de arriba filtra tanto por "Lockout" como por "Sperr". En un sistema en español, añade "bloqueo" al patrón de búsqueda.
¿Cuenta local o cuenta de dominio?
El script actúa sobre una cuenta local, el caso habitual en un VPS o en un servidor root independiente. Si se trata de una cuenta de dominio, o si trabajas en un controlador de dominio, desbloquea la cuenta así:
Unlock-ADAccount -Identity <nombre_de_usuario>
Ajustar o desactivar el umbral de bloqueo
Con $LockoutThreshold = 0 desactivas por completo la protección por bloqueo. En un servidor accesible desde Internet te lo desaconsejamos: sin bloqueo, un atacante puede probar tantas contraseñas como quiera. Es más razonable un umbral moderado, unos 10 intentos fallidos, combinado con las medidas de la sección siguiente.
Eliminar la causa: asegurar el acceso RDP de forma duradera
Una cuenta bloqueada solo es el síntoma. La causa real es un acceso RDP abierto a todo Internet. Estas cuatro medidas atacan el problema de raíz.
Limitar el RDP a tu propia dirección IP
Es, con diferencia, la medida más eficaz. Si el RDP solo es accesible desde tu propia dirección, todos los ataques automatizados se quedan en nada:
# Permitir el RDP entrante solo desde tu propia dirección IP
Set-NetFirewallRule -DisplayName 'Remote Desktop - User Mode (TCP-In)' -RemoteAddress '203.0.113.5'
El nombre para mostrar que aparece aquí vale para un Windows en inglés. En un sistema localizado, tanto en español como en alemán, el nombre es distinto. Puedes listar las reglas existentes y sus nombres exactos con Get-NetFirewallRule -DisplayGroup 'Remotedesktop'.
Bloquear la IP concreta de un atacante
Para las direcciones que te muestra el paso 4b del script, crea una regla de bloqueo específica:
New-NetFirewallRule -DisplayName 'Block RDP attacker 203.0.113.9' -Direction Inbound -Action Block -RemoteAddress '203.0.113.9'
Esto ayuda contra unas pocas fuentes persistentes, pero no sustituye a la restricción a tu propia dirección IP, porque los atacantes usan direcciones nuevas continuamente.
Cambiar el puerto RDP
Si el RDP ya no escucha en el puerto estándar 3389, los escaneos masivos habituales ni siquiera encuentran tu servicio. Nuestra guía Cambiar el puerto RDP en Windows sin reiniciar explica cómo cambiar el puerto sin reiniciar el servidor.
Contraseña fuerte y Network Level Authentication
Usa una contraseña larga y aleatoria, y deja activada Network Level Authentication (NLA). NLA exige la autenticación antes incluso de que se establezca una sesión y descarta así de antemano gran parte de los intentos automatizados.
Preguntas frecuentes
¿Por qué se bloquea mi cuenta de Windows al iniciar sesión por RDP?
¿Cuánto tiempo permanece bloqueada una cuenta?
¿Debería desactivar por completo el bloqueo de cuentas?
¿Cómo averiguo qué direcciones IP bloquean mi cuenta?
El script no desbloquea mi cuenta, ¿a qué se debe?
2026 KernelHost GmbH. Todos los derechos reservados. Esta guía está protegida por derechos de autor. Su publicación en otros sitios web, aunque sea de forma parcial o modificada, no está permitida sin nuestro consentimiento por escrito. Las citas con indicación de la fuente y un enlace son muy bienvenidas.

