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

Publicado el Actualizado el 8 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 = 0         # intentos fallidos hasta el bloqueo (0 = bloqueo DESACTIVADO, ver el texto)
$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-Host "  Limita ahora el RDP a tu propia dirección IP mediante el firewall." -ForegroundColor Yellow
    } 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

El script deja el umbral preconfigurado en 0 y desactiva así el bloqueo de cuentas. Al principio suena al revés, pero en un acceso RDP que está abierto a Internet es la mejor opción. El motivo: un atacante no necesita adivinar tu contraseña. Le basta con enviar unos cuantos intentos fallidos cada pocos minutos para que la cuenta quede bloqueada de forma permanente. El bloqueo no le afecta a él, sino únicamente a ti. Una función de protección se convierte así en una herramienta cómoda para mantenerte fuera de tu propio servidor.

Importante: desactivar el bloqueo no sustituye ninguna protección, solo elimina la equivocada. La protección contra el sondeo de contraseñas corresponde a un nivel más abajo, es decir, al firewall: si el RDP solo es accesible desde tu propia dirección IP, ningún atacante llega siquiera a la pantalla de inicio de sesión y ya no queda nada que contar. Por eso, aplica la sección siguiente antes de desactivar el bloqueo, no después.

Si por motivos operativos tienes que dejar el RDP abierto para direcciones cambiantes, usa en su lugar un umbral alto con una duración de bloqueo corta, por ejemplo $LockoutThreshold = 50 y $LockoutDuration = 5. Así conservas algo de efecto de freno sin quedarte fuera con cada escaneo. En un dominio con RDP interno sigue vigente la recomendación clásica de un umbral bajo, ya que allí el acceso no es alcanzable desde Internet de todos modos.

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 acceso RDP que está abierto a Internet, sí. Un atacante no necesita adivinar tu contraseña, le basta con enviar intentos fallidos con regularidad para mantener la cuenta bloqueada de forma permanente. El bloqueo entonces solo te afecta a ti. Desactívalo, pero limita el RDP en el mismo paso a tu propia dirección IP mediante el firewall, porque de lo contrario cambias un problema por otro. Si tienes que dejar el RDP abierto para direcciones cambiantes, elige en lugar de 0 un umbral alto con una duración de bloqueo corta.
¿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