Cómo proteger una VPS Windows contra ataques de fuerza bruta en RDP

Endurece una VPS Windows Server frente a fuerza bruta en RDP con firewall, cambio de puerto, política de bloqueo y baneo automático por IP.

Toda VPS Windows expuesta a internet pública empieza a recibir intentos de login en RDP pocos minutos después del arranque. Los bots barren rangos enteros de IP buscando el puerto 3389 abierto y lanzan diccionarios de contraseñas comunes contra cuentas como Administrator, admin, user y variantes. En una VPS sin protección, el Event Log se llena de Event ID 4625 (fallo de logon) en pocas horas — y basta una contraseña débil para que un atacante consiga entrar.

Este tutorial está dirigido a sysadmins de Windows que han aprovisionado una VPS recientemente y quieren reducir la superficie de ataque del RDP antes de poner el servidor en producción. Las medidas aquí no requieren software de terceros — usan solo recursos nativos de Windows Server 2019/2022/2025. Tiempo estimado: 30 a 45 minutos para aplicar todas las capas.

El enfoque es por capas — ninguna medida por sí sola es suficiente. Vas a aplicar cuatro defensas: política de bloqueo de cuenta, cambio del puerto por defecto del RDP, restricción de firewall por IP de origen y bloqueo automático de IPs ofensoras mediante Tarea Programada disparada por evento.

Requisitos previos

Requisitos previos

VPS Windows Server 2019, 2022 o 2025 con acceso administrativo. Conexión RDP actual operativa. Conoce la IP pública de tu oficina/casa antes de empezar — si restringes el RDP y pierdes esa IP, vas a necesitar la consola de la VPS para recuperar el acceso.

Puerto RDP por defecto TCP 3389
Event ID fallo de logon 4625
Servicio del RDP TermService

Antes de empezar, abre el Visor de Eventos en Registros de Windows > Seguridad y filtra por Event ID 4625. En una VPS expuesta durante más de 24 horas normalmente verás cientos de intentos provenientes de IPs en China, Rusia, Brasil y EE. UU. Ese es el baseline que vamos a derribar.

Aplicar política de bloqueo de cuenta

La política de bloqueo hace que Windows deshabilite una cuenta temporalmente tras N intentos fallidos. Sin esto, un atacante puede disparar miles de contraseñas por minuto contra la cuenta Administrator. Con un bloqueo de 5 intentos y una duración de 30 minutos, el atacante consigue probar como máximo 240 contraseñas por día por cuenta — haciendo inviable el ataque de diccionario.

01

Abre el Editor de Directivas de Grupo Local (gpedit.msc) y navega hasta:

Configuración del equipo > Configuración de Windows > Configuración de seguridad >
Directivas de cuenta > Directiva de bloqueo de cuenta

Configura los tres valores:

  • Umbral de bloqueo de cuenta: 5 intentos no válidos
  • Duración del bloqueo de cuenta: 30 minutos
  • Restablecer la cuenta de bloqueo después de: 30 minutos
02

Aplica la política inmediatamente sin esperar al ciclo de 90 minutos del Group Policy:

gpupdate /force

Verifica que quedó activa:

net accounts

Deberías ver Umbral de bloqueo: 5 y Duración del bloqueo (minutos): 30 en la salida.

No uses bloqueo permanente

Definir la duración del bloqueo como 0 (permanente) parece más seguro, pero crea riesgo operativo: cualquier error de tipeo tuyo bloquea la cuenta hasta intervención manual. 30 minutos es el equilibrio estándar recomendado por Microsoft y el CIS Benchmark.

Cambiar el puerto por defecto del RDP

Cambiar de 3389 a un puerto alto (por encima de 49152, rango dinámico) elimina el ruido de los escáneres automatizados que solo buscan el puerto por defecto. No es seguridad real contra ataque dirigido — nmap -p- IP aún lo encuentra — pero reduce los Event ID 4625 en un 90%+ en VPS expuestas.

01

Abre el Editor del Registro (regedit) y navega hasta:

HKLM\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp

Localiza la clave PortNumber, cámbiala a decimal y escribe el nuevo puerto (ejemplo: 54289). Evita puertos conocidos de otros servicios (8080, 8443, 3306).

02

Añade la regla de firewall para el nuevo puerto antes de reiniciar el servicio:

New-NetFirewallRule -DisplayName "RDP Custom Port 54289 TCP" `
  -Direction Inbound -LocalPort 54289 -Protocol TCP -Action Allow

New-NetFirewallRule -DisplayName "RDP Custom Port 54289 UDP" `
  -Direction Inbound -LocalPort 54289 -Protocol UDP -Action Allow
03

Reinicia el servicio de Terminal Server para aplicar el cambio:

Restart-Service TermService -Force

Tu sesión actual se cortará. Reconéctate usando IP:54289 en el cliente RDP (la Conexión a Escritorio Remoto de Windows acepta el sufijo :puerto).

Añade la regla antes de reiniciar

Si reinicias el TermService sin haber creado la regla de firewall para el nuevo puerto, el RDP queda inaccesible. En una VPS Hostini puedes volver a través de la consola del panel — pero para evitar ese dolor, asegúrate de tener las dos reglas antes del Restart-Service.

Restringir RDP por IP de origen

La medida más efectiva: el firewall solo acepta conexiones RDP desde IPs específicas. Funciona bien si tu equipo accede desde IPs fijas (oficina, VPN corporativa). No funciona si necesitas acceder desde redes residenciales con IP dinámica — en ese caso, considera la alternativa del túnel WireGuard.

01

Identifica las IPs que deben tener permiso. Consulta tu IP pública ahora:

(Invoke-WebRequest -Uri "https://ifconfig.me/ip").Content

Anota esa IP y la de cualquier otra ubicación que necesite acceso.

02

Edita la regla de firewall que creaste en la sección anterior para que acepte solo esas IPs:

Set-NetFirewallRule -DisplayName "RDP Custom Port 54289 TCP" `
  -RemoteAddress @("203.0.113.10", "198.51.100.42")

Sustituye las IPs del ejemplo por las tuyas. Para un rango CIDR usa formato 203.0.113.0/24.

03

Confirma que la regla queda restringida:

Get-NetFirewallRule -DisplayName "RDP Custom Port 54289 TCP" |
  Get-NetFirewallAddressFilter

El campo RemoteAddress debe mostrar las IPs que definiste, no Any.

Lista permitida vía WireGuard cuando la IP es dinámica

Si accedes desde internet residencial con IP dinámica, en vez de mantener actualizada la lista permitida, instala un servidor WireGuard en la propia VPS, expón solo UDP 51820 públicamente y restringe el RDP a 10.0.0.0/24 (red interna del túnel). Pasas a conectarte vía VPN antes que por RDP.

Bloquear automáticamente IPs ofensoras

Incluso con bloqueo de cuenta y puerto cambiado, si no puedes restringir por IP de origen (atención al público, equipo distribuido), configura un bloqueo dinámico: cada vez que aparece un Event ID 4625 por encima de un umbral, una Tarea Programada dispara un script PowerShell que añade la IP de origen a una regla de firewall de bloqueo.

01

Guarda el script siguiente en C:\Scripts\BlockBruteforceIP.ps1:

param([string]$EventRecordID)

$event = Get-WinEvent -LogName Security -FilterXPath `
  "*[System[EventRecordID=$EventRecordID]]"

$ip = ($event.Properties | Where-Object { $_.Value -match '^\d+\.\d+\.\d+\.\d+$' } |
  Select-Object -First 1).Value

if (-not $ip -or $ip -eq "127.0.0.1") { exit }

$ruleName = "AutoBlock-$ip"
if (-not (Get-NetFirewallRule -DisplayName $ruleName -ErrorAction SilentlyContinue)) {
    New-NetFirewallRule -DisplayName $ruleName -Direction Inbound `
      -RemoteAddress $ip -Action Block | Out-Null
    Add-Content "C:\Scripts\blocked-ips.log" "$(Get-Date -Format o) BLOCKED $ip"
}
02

Crea la Tarea Programada disparada por evento. Abre el Programador de tareas > Crear tarea:

  • General > Ejecutar con los privilegios más altos: marcado
  • Desencadenadores > Nuevo: Iniciar la tarea = Al producirse un evento, Registro = Seguridad, Id. de evento = 4625
  • Acciones > Nueva: Programa = powershell.exe, Argumentos:
-ExecutionPolicy Bypass -File C:\Scripts\BlockBruteforceIP.ps1 -EventRecordID $(EventRecordID)

Para pasar $(EventRecordID) correctamente, tienes que editar el XML de la tarea después de crearla — exporta la tarea, edita el elemento <ValueQueries> añadiendo el RecordId, y vuelve a importarla.

03

Prueba forzando un fallo de logon desde otra máquina y confirma que la IP ha sido bloqueada:

Get-NetFirewallRule | Where-Object DisplayName -like "AutoBlock-*"

También puedes revisar el archivo C:\Scripts\blocked-ips.log para ver el histórico.

Herramienta lista: IPBan

Si montar la Tarea Programada manualmente te parece frágil, el proyecto open-source IPBan hace exactamente esto de forma robusta y gratuita. Monitorea los Event Logs en tiempo real y mantiene reglas de firewall optimizadas. Para entornos más grandes, vale la pena.

Verificación

Después de aplicar las cuatro capas, confirma cada una ejecutando:

# Política de bloqueo
net accounts | findstr "bloqueo"

# Nuevo puerto RDP activo
Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
  | Select-Object PortNumber

# Firewall acepta conexión en el nuevo puerto
Test-NetConnection -ComputerName localhost -Port 54289

# La cuenta quedó efectivamente "blindada" — intenta login incorrecto 5 veces desde otra IP
# y verifica el Event Log buscando Event ID 4740 (Cuenta bloqueada)
Get-WinEvent -LogName Security -MaxEvents 50 |
  Where-Object Id -eq 4740 | Format-Table TimeCreated, Message -AutoSize

Espera 24 horas y vuelve al Visor de Eventos. Deberías ver los Event ID 4625 caer de cientos/miles por día a decenas o cero, dependiendo de cuán expuesto haya quedado el puerto original antes del cambio.

Próximos pasos

  • Configura NLA (Network Level Authentication) si no está activo — exige autenticación antes del handshake completo de RDP, reduciendo la superficie de ataque a vulnerabilidades pre-auth.
  • Considera migrar del RDP nativo a Azure Bastion o a un gateway RDS con MFA si el entorno lo justifica.
  • Implementa auditoría de logon exitoso (Event ID 4624) y alertas por email para logins fuera del horario habitual.
  • Haz backup periódico del registro (HKLM\System\CurrentControlSet\Control\Terminal Server) — así reviertes rápido si algo se rompe.
  • Si estás aprovisionando una VPS nueva para producción, una VPS Hostini Windows ya viene con consola fuera de banda accesible desde el panel — así que aunque te bloquees fuera del RDP aplicando estas reglas, la recuperación no exige ticket de soporte.

Preguntas frecuentes

¿Cambiar el puerto del RDP de 3389 a otro realmente ayuda?

Sí, pero como medida de reducción de ruido, no como seguridad real. Los escáneres automatizados que rastrean internet entera se concentran en el 3389 y dejan de encontrarte cuando lo cambias. Atacantes dirigidos aún te localizan con nmap. Combínalo con política de bloqueo y baneo por IP — un puerto alternativo por sí solo es seguridad por oscuridad.

¿Por qué no basta con dejar que el Windows Defender Firewall haga el trabajo?

El firewall por defecto permite RDP desde cualquier origen en cuanto habilitas el Escritorio Remoto. No tiene lógica nativa de detección de fuerza bruta — bloquea o permite según reglas estáticas. Necesitas añadir reglas de origen (lista de IPs permitidas) o un mecanismo de bloqueo dinámico vía Visor de Eventos.

¿Es seguro cerrar el puerto 3389 y usar solo un túnel SSH/WireGuard?

Es el enfoque más seguro. Expones solo el puerto del túnel (UDP 51820 para WireGuard, por ejemplo) y el RDP pasa a aceptar conexiones solo desde 127.0.0.1 o desde la red interna del túnel. Un atacante en internet pública ni siquiera consigue un handshake TCP con el RDP. Contrapartida: hay que configurar el cliente en cada máquina desde la que vayas a administrar.

¿La política de bloqueo no acaba bloqueando al propio administrador?

Puede bloquearte si te equivocas de contraseña durante una sesión real. Por eso la recomendación es un bloqueo de 15-30 minutos, no permanente, y mantener una segunda cuenta administrativa con nombre distinto para recuperación. En una VPS Hostini también tienes acceso a la consola desde el panel aunque el RDP bloquee la cuenta principal.

¿El Event ID 4625 detecta todos los intentos fallidos de RDP?

Detecta los que llegan a la capa de autenticación, que es el caso cuando NLA (Network Level Authentication) está habilitado y el cliente envía credenciales. Los intentos previos al handshake completo (probe scans) no generan 4625 — aparecen en el Security Log como Event 4624 (logon) o en los logs de TerminalServices. Para cobertura total combina 4625 + Microsoft-Windows-RemoteDesktopServices/Operational.

¿Merece la pena usar fail2ban en Windows?

Fail2ban es nativo de Linux. En Windows el equivalente funcional es una combinación de Tarea Programada disparada por Event ID 4625 + un script PowerShell que añade la IP ofensora a una regla de firewall de bloqueo. Existen herramientas open-source que empaquetan esto (RDPGuard, IPBan, EvlWatcher) — IPBan es gratuito y es lo más parecido a una experiencia tipo fail2ban.

Temas:
Próximos pasos Cloud Ryzen con NVMe y protección DDoS siempre activa.Pon en producción en un VPS Hostini →
¿Te resultó útil este tutorial?
Hablar por WhatsApp