Error de RDP: desbloquear una cuenta de Windows bloqueada (PowerShell)

Publicado el Actualizado el 7 min de lectura

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

  1. Muestra con net accounts la directiva de bloqueo de cuentas actual, es decir, el umbral, la duración del bloqueo y la ventana de observación.
  2. Desbloquea la cuenta indicada en $Username a través del proveedor de directorio WinNT. Es el equivalente de Unlock-ADAccount para cuentas locales.
  3. Ajusta la directiva, siempre que $ApplyPolicy esté en $true. Con los valores predeterminados el bloqueo se vuelve menos agresivo, y con $LockoutThreshold = 0 lo desactivas por completo.
  4. 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?
Windows bloquea una cuenta en cuanto se alcanza el número de intentos de inicio de sesión fallidos definido en la directiva de bloqueo. En un servidor con el puerto RDP abierto a Internet, casi siempre son ataques automatizados los que provocan ese bloqueo.
¿Cuánto tiempo permanece bloqueada una cuenta?
El tiempo que indique la duración de bloqueo configurada, a menudo 15 o 30 minutos. Después vuelve a ser posible iniciar sesión. Con el script de esta guía también puedes levantar el bloqueo de inmediato.
¿Debería desactivar por completo el bloqueo de cuentas?
En un servidor accesible públicamente, mejor no. Sin bloqueo, un atacante puede probar tantas contraseñas como quiera. Es más razonable un umbral moderado de unos 10 intentos, junto con una regla de firewall que limite el RDP a tu propia dirección IP.
¿Cómo averiguo qué direcciones IP bloquean mi cuenta?
El ID de evento 4740 del registro de seguridad documenta los bloqueos en sí, y el ID de evento 4625, los inicios de sesión fallidos junto con su IP de origen. El script de esta guía analiza ambos de forma automática.
El script no desbloquea mi cuenta, ¿a qué se debe?
El script actúa sobre una cuenta local. En una cuenta de dominio o en un controlador de dominio, desbloquea con Unlock-ADAccount. Comprueba además que PowerShell se esté ejecutando realmente como administrador.

Windows Server Windows RDP Remote Desktop PowerShell Bloqueo de cuentas Fuerza bruta Seguridad del servidor