Si ves una avalancha de eventos 4625 sin IP al publicar RDS/RDWeb en Windows Server 2016, aquí tienes un procedimiento completo para descubrir la IP real, bloquear el origen y endurecer tu despliegue sin perder disponibilidad.
Contexto y diagnóstico: por qué aparecen 4625 sin IP en RDWeb
Cuando expones RDWeb (IIS) con certificado SSL y, por ejemplo, MFA de Duo, es habitual ver intentos de inicio de sesión fallidos (eventos 4625) en el registro de Seguridad. En muchos de esos eventos el campo Source Network Address aparece como -
. Esto no significa que no exista IP de origen; significa que la autenticación sucede localmente dentro del servidor web, y quien llama a la validación es el worker process de IIS (w3wp.exe
). Por ello, la IP del cliente no queda en el 4625 sino en el log de IIS (c-ip
).
Además, si observas nombres de usuario aleatorios (por ejemplo, recepsto
o admin123
) o una misma cuenta probada desde multitud de orígenes, se trata de password spraying automatizado contra el portal.
Cliente ─HTTPS─> IIS (RDWeb: w3wp.exe) ──> LSA valida credenciales
│
├─ Evento 4625 (sin IP real)
└─ IIS log (c-ip = IP real del cliente)
Objetivo operativo
Lo que necesitamos es: (1) extraer la IP real del atacante, (2) correlacionar con los 4625 para entender el patrón y (3) mitigar inmediatamente con límites, bloqueo y MFA adecuado, mientras (4) endurecemos la exposición para que el ruido baje de forma sostenida.
Paso 1 — Cómo obtener la IP de origen real
IIS logs (la fuente definitiva de la IP)
Ruta típica: C:\inetpub\logs\LogFiles\W3SVC*
. Abre el archivo del día y busca solicitudes a /RDWeb
cerca de las horas en que ves 4625. La columna clave es c-ip
. Un fragmento de ejemplo en formato W3C podría verse así (campos ilustrativos):
#Fields: date time s-ip cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) sc-status sc-substatus sc-win32-status time-taken
2025-08-16 07:23:11 10.0.0.5 POST /RDWeb/Pages/en-US/login.aspx - 443 - 203.0.113.45 Mozilla/5.0 401 2 5 97
El valor 203.0.113.45
es la IP a bloquear o limitar.
¿Hay un proxy o WAF delante? Usa X-Forwarded-For
Si tienes un reverse proxy/WAF (por ejemplo, un balanceador o CDN), es probable que c-ip
sea la IP del proxy. En ese caso:
- En IIS Manager → <Sitio RDWeb> → Logging → Select Fields → Add Field, añade un campo personalizado de tipo Request Header con nombre
X-Forwarded-For
. - En Dynamic IP Restrictions, activa Proxy Mode (ver más adelante) para que las restricciones usen la IP real del cliente tomada de ese encabezado.
Si usas RD Gateway
Además de RDWeb, revisa el log de RD Gateway en: Event Viewer → Applications and Services Logs → Microsoft → Windows → TerminalServices-Gateway → Operational. Ahí verás la IP del cliente que intenta atravesar el Gateway. Si tus usuarios deben entrar exclusivamente por RD Gateway sobre 443, no deberías exponer 3389/TCP a Internet.
Más detalle: Failed Request Tracing (FREB)
Si necesitas trazar exactamente qué URL invocan y con qué frecuencia, habilita Failed Request Tracing en el sitio RDWeb y crea una regla para las rutas de /RDWeb
. Te dará contexto de códigos HTTP, módulos de autenticación y tiempos.
Paso 2 — Auditoría avanzada para investigar
Activa y corrige la auditoría para tener visibilidad útil sin generar tormentas de eventos.
Directiva de auditoría
- En GPMC: Computer Configuration → Windows Settings → Security Settings → Advanced Audit Policy Configuration.
- Logon/Logoff → Audit Logon: Success y Failure.
- (En controladores de dominio) Account Logon → Audit Credential Validation: Success y Failure (para eventos 4776 en el DC).
Comandos rápidos (en el servidor)
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
En los controladores de dominio:
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable
Filtrado útil en Visor de eventos
Filtra por ID 4625 en el registro Security y añade como columnas: Cuenta, Código de error, Proceso de llamada, Hora. La IP no aparecerá (aparecerá -
) porque la verás en IIS. El valor está en la correlación temporal con las entradas de IIS (c-ip
).
Correlación rápida con PowerShell (top IPs por tasa)
El siguiente script localiza el log de IIS más reciente, extrae los campos relevantes y devuelve las IP con más solicitudes a /RDWeb
en la última hora. Útil para decisiones de bloqueo:
$hours = 1
$log = Get-ChildItem 'C:\inetpub\logs\LogFiles\W3SVC*' -File |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
if (-not $log) { throw "No se encontró log de IIS." }
Lee cabeceras (#Fields) para mapear columnas dinámicamente
\$header = (Select-String -Path \$log.FullName -Pattern '^#Fields:' -CaseSensitive -SimpleMatch | Select-Object -First 1).Line
\$fields = \$header.Replace('#Fields: ','').Split(' ')
\$idx = @{
date = \[array]::IndexOf(\$fields,'date')
time = \[array]::IndexOf(\$fields,'time')
cip = \[array]::IndexOf(\$fields,'c-ip')
stem = \[array]::IndexOf(\$fields,'cs-uri-stem')
}
\$cutoff = (Get-Date).AddHours(-\$hours)
\$lines = Get-Content \$log.FullName | Where-Object { $\_ -notmatch '^#' }
\$records = foreach (\$l in \$lines) {
\$parts = \$l.Split(' ')
if (\$parts.Count -lt \$fields.Count) { continue }
try {
\$dt = \[datetime]::Parse("\$(\$parts\[\$idx.date]) \$(\$parts\[\$idx.time])")
} catch { continue }
if (\$dt -lt \$cutoff) { continue }
\$obj = \[pscustomobject]@{
When = \$dt
CIP = \$parts\[\$idx.cip]
Uri = \$parts\[\$idx.stem]
}
if (\$obj.Uri -like '/RDWeb\*') { \$obj }
}
\$records | Group-Object CIP | Sort-Object Count -Descending |
Select-Object @{n='IP';e={\$*.Name}},
@{n='Solicitudes\ultima\hora';e={\$*.Count}} -First 20 </code></pre>
<h2>Paso 3 — Mitigación inmediata (ruido y riesgo)</h2>
<h3>Bloqueo/permitir por IP en el perímetro</h3>
<ul>
<li>Si es posible, aplica un <strong>allowlist</strong> de rangos conocidos (oficina/VPN). Esto corta el ruido de Internet de un tajo.</li>
<li>Apoya con <strong>geobloqueo</strong> si no tienes usuarios fuera de ciertas regiones.</li>
</ul>
<h3>IIS: IP and Domain Restrictions + Dynamic IP Restrictions</h3>
<p>Instala los <em>role services</em> de IIS para <strong>IP and Domain Restrictions</strong> y <strong>Dynamic IP Restrictions</strong> (desde <em>Server Manager → Add Roles and Features</em>). En el sitio de RDWeb:</p>
<ol>
<li><strong>IP and Domain Restrictions</strong>: puedes permitir solo rangos internos o de VPN.</li>
<li><strong>Dynamic IP Restrictions</strong>:
<ul>
<li><strong>Denegar por tasa</strong>: por ejemplo, > <strong>30 solicitudes en 60s</strong> → bloqueo temporal.</li>
<li><strong>Denegar por concurrencia</strong>: por ejemplo, > <strong>5 solicitudes concurrentes</strong> → bloqueo temporal.</li>
<li><strong>Proxy Mode</strong>: habilítalo si estás detrás de un proxy/WAF y usas <code>X-Forwarded-For</code>.</li>
</ul>
</li>
</ol>
<p>Configuración con <code>appcmd</code> (ajusta el nombre del sitio si procede):</p>
<pre><code>%windir%\system32\inetsrv\appcmd set config "Default Web Site/RDWeb" /section:dynamicIpSecurity /denyByRequestRate.enabled:true /denyByRequestRate.maxRequests:30 /denyByRequestRate.timePeriod:00:01:00 /denyByConcurrentRequests.enabled:true /denyByConcurrentRequests.maxConcurrentRequests:5 /enableProxyMode:true
</code></pre>
<h3>Cerrar 3389/TCP a Internet</h3>
<p>El acceso RDP debe entrar <strong>solo por RD Gateway/HTTPS (443)</strong>. Verifica que no haya reglas de publicación ni NAT exponiendo <code>3389</code>. Bloquéalo en el <em>edge</em> y en cualquier <em>NSG/ACL</em> intermedio.</p>
<h3>MFA donde importa: RD Gateway</h3>
<p>RDWeb con MFA protege el <em>portal</em>, pero <strong>aplica MFA también en RD Gateway</strong> para proteger la sesión RDP. Si tu operación lo permite, configura el <strong>fail-closed</strong> para evitar bypass cuando el proveedor MFA no está disponible.</p>
<h3>Política de bloqueo de cuentas</h3>
<p>Establece un umbral razonable para evitar bloqueos masivos por denegación de servicio:</p>
<ul>
<li><strong>Intentos</strong>: ~10</li>
<li><strong>Reset</strong>: 15–30 minutos</li>
<li><strong>Duración</strong>: 15–30 minutos</li>
</ul>
<p>Aplica especialmente a cuentas privilegiadas. Usa <em>Smart Lockout</em> si tu directorio lo soporta.</p>
<h2>Paso 4 — Endurecimiento sostenido</h2>
<h3>Coloca RDWeb detrás de VPN / Zero Trust</h3>
<p>Publica RDWeb mediante soluciones que autentican <strong>antes</strong> de llegar al portal (p. ej., VPN corporativa, <em>Secure Access</em>, <em>reverse proxies</em> con identidad). Así evitas que Internet toque <em>login.aspx</em>.</p>
<h3>Restringe quién puede iniciar sesión</h3>
<ul>
<li>En <strong>RD Gateway</strong>, usa <strong>CAP/RAP</strong> con grupos de seguridad específicos.</li>
<li>En GPO local o de dominio, limita <strong>Allow log on through Remote Desktop Services</strong> a los grupos que realmente lo requieren.</li>
<li>Aplica <strong>Deny log on through Remote Desktop Services</strong> a <em>Guests</em> y cuentas no utilizadas.</li>
<li><strong>Deshabilita/renombra</strong> cuentas locales que no se usen.</li>
</ul>
<h3>TLS y cifrado</h3>
<ul>
<li>En <strong>Windows Server 2016</strong>, <strong>fuerza TLS 1.2</strong> y deshabilita protocolos débiles. (TLS 1.3 no está disponible en 2016).</li>
<li>Aplica conjuntos de cifrado modernos y desactiva RC4/3DES.</li>
</ul>
<h3>Actualizaciones y líneas base</h3>
<ul>
<li>Mantén el servidor con <strong>parches al día</strong>.</li>
<li>Aplica las <strong>Security Baselines</strong> de Microsoft para Server 2016 como base de endurecimiento.</li>
</ul>
<h3>Detección y alertas</h3>
<ul>
<li>Crea alertas por <strong>umbral de 4625</strong> por minuto y por origen (una IP que dispare cientos de peticiones).</li>
<li>Analiza tendencias de <strong><code>c-ip</code></strong> en IIS para <strong>bloquear proactivamente</strong> los peores orígenes.</li>
</ul>
<h2>Recetas prácticas (paso a paso)</h2>
<h3>Habilitar campos personalizados de logging (X-Forwarded-For)</h3>
<ol>
<li>Abrir <strong>IIS Manager</strong> → <em>Default Web Site</em> (o tu sitio) → <strong>Logging</strong>.</li>
<li>Click en <strong>Select Fields</strong> → <strong>Add Field…</strong>.</li>
<li><strong>Field name</strong>: <code>X-Forwarded-For</code> — <strong>Source</strong>: <em>Request Header</em> — <strong>Header name</strong>: <code>X-Forwarded-For</code>.</li>
<li>Guardar y reciclar el <em>App Pool</em> de RDWeb si procede.</li>
</ol>
<h3>Instalar y configurar Dynamic IP Restrictions</h3>
<ol>
<li>En <em>Server Manager</em> → <em>Add Roles and Features</em> → <em>Web Server (IIS)</em> → <em>Web Server</em> → <em>Security</em>, marca <strong>IP and Domain Restrictions</strong> y <strong>Dynamic IP Restrictions</strong>.</li>
<li>En el sitio <strong>RDWeb</strong>, abre <strong>Dynamic IP Restrictions</strong> y marca:
<ul>
<li><em>Deny IP addresses based on the number of concurrent requests</em> = <strong>5</strong>.</li>
<li><em>Deny IP addresses based on the number of requests over a period of time</em> = <strong>30</strong> en <strong>60</strong> segundos.</li>
<li><em>Enable Proxy Mode</em> si usas <em>X-Forwarded-For</em>.</li>
</ul>
</li>
</ol>
<h3>Bloquear IPs con Windows Firewall (rápido)</h3>
<pre><code class="language-powershell"># Sustituye 203.0.113.45 por la IP a bloquear
New-NetFirewallRule -DisplayName "Bloqueo RDWeb 203.0.113.45" `
-Direction Inbound -Action Block -RemoteAddress 203.0.113.45 `
-Protocol TCP -LocalPort 443
</code></pre>
<p><em>Nota:</em> preferible bloquear en el <strong>firewall perimetral/WAF</strong> para cortar antes el tráfico.</p>
<h3>Filtrar 4625 que vienen de RDWeb</h3>
<p>Muchos 4625 generados por RDWeb tendrán el <em>Caller</em> asociado a <code>w3wp.exe</code>. Un filtro textual rápido:</p>
<pre><code class="language-powershell">Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} |
Where-Object { $.Message -like '*w3wp.exe*' -or $.Message -like 'Logon Process' } |
Select-Object TimeCreated, Id, Message -First 20
</code></pre>
<h3>Top IPs → reglas de bloqueo (automatizable)</h3>
<p>Extiende el script de IIS anterior para convertir el <em>top N</em> en reglas de firewall temporales. Asegúrate de <strong>revisar falsos positivos</strong> (IP compartidas, NAT de clientes legítimos, etc.).</p>
<h2>Tabla de decisión: qué mirar y qué hacer</h2>
<table>
<thead>
<tr>
<th>Situación</th>
<th>Dónde mirar</th>
<th>Señales</th>
<th>Acciones inmediatas</th>
<th>Prevención</th>
</tr>
</thead>
<tbody>
<tr>
<td>4625 constantes sin IP</td>
<td>Security (4625) + IIS <code>c-ip</code></td>
<td>Muchos usuarios aleatorios</td>
<td>Bloquear IP origen; activar Dynamic IP Restrictions</td>
<td>Allowlist/VPN, Zero Trust</td>
</tr>
<tr>
<td>RD Gateway en uso</td>
<td>TS-Gateway/Operational</td>
<td>IP repetidas en corto intervalo</td>
<td>CAP/RAP restrictivas, MFA en Gateway</td>
<td>Geobloqueo; grupos mínimos</td>
</tr>
<tr>
<td>Con proxy/WAF delante</td>
<td>IIS Logging + X-Forwarded-For</td>
<td><code>c-ip</code> = proxy</td>
<td>Habilitar Proxy Mode y registrar XFF</td>
<td>Rate limiting en WAF</td>
</tr>
<tr>
<td>Bloqueos de cuenta</td>
<td>Security 4740/4767, DC 4776</td>
<td>Cuentas sensibles afectadas</td>
<td>Ajustar umbral y reset</td>
<td>Smart Lockout / MFA obligatoria</td>
</tr>
<tr>
<td>3389 expuesto</td>
<td>Revisión de NAT/ACLs</td>
<td>Intentos RDP directos</td>
<td>Cerrar 3389 al exterior</td>
<td>Usar <em>solo</em> RD Gateway (443)</td>
</tr>
</tbody>
</table>
<h2>Errores comunes (y cómo evitarlos)</h2>
<ul>
<li><strong>Buscar la IP en el 4625</strong>: no está ahí en este escenario. Mírala en <strong>IIS</strong>.</li>
<li><strong>Bloquear en el host sin ver el todo</strong>: bloquea en el <strong>perímetro</strong> para evitar consumo de recursos del servidor.</li>
<li><strong>Confiar solo en RDWeb con MFA</strong>: pon <strong>MFA en RD Gateway</strong>, es la barrera real de RDP.</li>
<li><strong>No activar Proxy Mode</strong>: sin él, Dynamic IP Restrictions puede bloquear a tu propio proxy y no al cliente real.</li>
<li><strong>Permitir “Domain Users” en RDS</strong>: restringe grupos al mínimo necesario.</li>
</ul>
<h2>Checklist accionable</h2>
<ul>
<li>✅ Revisar <code>C:\inetpub\logs\LogFiles\W3SVC*</code> y obtener <strong>c-ip</strong> alrededor de cada 4625.</li>
<li>✅ Si hay proxy/WAF, <strong>registrar X-Forwarded-For</strong> y activar <strong>Proxy Mode</strong>.</li>
<li>✅ <strong>Dynamic IP Restrictions</strong> (30 req/60s; 5 concurrentes).</li>
<li>✅ <strong>Cerrar 3389</strong> a Internet; todo por <strong>443</strong>.</li>
<li>✅ <strong>MFA en RD Gateway</strong> (idealmente fail-closed).</li>
<li>✅ <strong>Política de bloqueo</strong> moderada (10 intentos; reset 15–30 min).</li>
<li>✅ <strong>CAP/RAP</strong> y <strong>Allow log on through RDS</strong> mínimos.</li>
<li>✅ <strong>TLS 1.2</strong> reforzado; protocolos débiles deshabilitados.</li>
<li>✅ <strong>Alertas</strong> por 4625/Origen y análisis de tendencias en IIS.</li>
</ul>
<h2>Plan en 3 pasos (priorizado)</h2>
<ol>
<li><strong>Hoy</strong>: inspeccionar IIS para IPs y <strong>bloquear</strong> en firewall/WAF; habilitar <strong>Dynamic IP Restrictions</strong> y, si aplica, <strong>Proxy Mode</strong>.</li>
<li><strong>Próximas 48 h</strong>: completar <strong>auditoría avanzada</strong>, validar que <strong>3389</strong> no está expuesto, mover/aplicar <strong>MFA a RD Gateway</strong>, ajustar política de bloqueo.</li>
<li><strong>Corto plazo</strong>: publicar RDWeb detrás de <strong>VPN/Zero Trust</strong>, restringir accesos por <strong>CAP/RAP</strong> y GPO, aplicar <strong>baselines</strong> y reforzar <strong>TLS 1.2</strong>.</li>
</ol>
<h2>Preguntas frecuentes</h2>
<h3>¿Por qué el 4625 enseña “Source Network Address: -”?</h3>
<p>Porque la autenticación la ejecuta localmente el proceso <code>w3wp.exe</code> de IIS llamando a LSA; la IP real está en el <strong>log de IIS</strong> (<code>c-ip</code>) y, si hay proxy, en el <strong>encabezado X-Forwarded-For</strong>.</p>
<h3>¿Basta con MFA en RDWeb?</h3>
<p>No. RDWeb protege el portal, pero el recurso crítico es el <strong>RDP</strong>. Aplica <strong>MFA en RD Gateway</strong> para que ninguna sesión entre sin MFA.</p>
<h3>¿Debo bloquear cuentas tras pocos intentos?</h3>
<p>Bloqueos muy agresivos pueden provocar <em>DoS</em> a usuarios legítimos. Mantén umbrales moderados y complementa con <strong>rate limiting</strong>, WAF y MFA.</p>
<h3>¿TLS 1.3 en Windows Server 2016?</h3>
<p>No está disponible. Refuerza <strong>TLS 1.2</strong> y deshabilita protocolos/cifrados débiles.</p>
<h2>Apéndice: filtros y utilidades</h2>
<h3>XML de filtro para 4625 (Visor de eventos)</h3>
<p>En <em>Security → Filter Current Log… → XML</em>, puedes usar un filtro que limite por rango de tiempo (ajústalo a tus horas):</p>
<pre><code><QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[System[(EventID=4625) and TimeCreated[timediff(@SystemTime) <= 3600000]]]
</Select>
</Query>
</QueryList>
</code></pre>
<h3>Identificar intentos contra rutas concretas de RDWeb</h3>
<p>Filtra en IIS los accesos a <code>/RDWeb/Pages/en-US/login.aspx</code> (o el idioma correspondiente) y agrupa por <code>c-ip</code>. Esas IPs son candidatas a bloqueo.</p>
<h3>Script para crear reglas temporales de bloqueo (con revisión)</h3>
<pre><code class="language-powershell">$top = <# usa el resultado del script de "Top IPs" de arriba #>
foreach ($entry in $top) {
$ip = $entry.IP
if ($ip -and $ip -ne '-') {
Write-Host "Revisando $ip... (aplicar bloqueo si procede)"
# New-NetFirewallRule -DisplayName "Bloqueo temporal $ip" -Direction Inbound -Action Block -RemoteAddress $ip -Protocol TCP -LocalPort 443
}
}
</code></pre>
<p>Deja el comando de creación de regla comentado hasta validar falsos positivos.</p>
<h2>Conclusiones</h2>
<p>Los eventos <strong>4625 sin IP</strong> en despliegues de <strong>RDWeb (Windows Server 2016)</strong> no son un agujero de visibilidad: la IP está en otro lugar, <strong>IIS</strong>. Con una combinación de <strong>análisis de logs</strong>, <strong>rate limiting</strong>, <strong>bloqueo perimetral</strong>, <strong>MFA en el Gateway</strong> y <strong>endurecimiento</strong> (grupos mínimos, TLS 1.2, baselines), puedes <strong>reducir drásticamente</strong> el ruido, cortar los ataques automatizados y mantener el acceso remoto estable y seguro.</p>
<hr />
<p><strong>Comandos y ubicaciones útiles (resumen)</strong></p>
<ul>
<li><strong>IIS logs</strong>: <code>C:\inetpub\logs\LogFiles\W3SVC*</code> (campo <code>c-ip</code> y, con proxy, <code>X-Forwarded-For</code>).</li>
<li><strong>Auditoría</strong>:
<pre><code>auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable # en DCs
Eventos de RD Gateway: Applications and Services Logs → Microsoft → Windows → TerminalServices-Gateway → Operational.
Dynamic IP Restrictions (appcmd):
%windir%\system32\inetsrv\appcmd set config "Default Web Site/RDWeb" /section:dynamicIpSecurity /denyByRequestRate.enabled:true /denyByRequestRate.maxRequests:30 /denyByRequestRate.timePeriod:00:01:00 /denyByConcurrentRequests.enabled:true /denyByConcurrentRequests.maxConcurrentRequests:5 /enableProxyMode:true
Con esto obtendrás la IP de origen real, podrás bloquear o limitar de forma efectiva las fuentes de ataque y reducirás el volumen de 4625, manteniendo RDS accesible de forma segura.