Acerca de esta documentación

Este es el sitio oficial de documentación para DNSServer.DebugLogParser, un módulo de PowerShell que transforma los archivos de registro de depuración del servidor DNS de Windows en datos CSV estructurados y analizables.

Acerca del módulo

DNSServer.DebugLogParser nació de una necesidad real: los registros de depuración del servidor DNS de Windows son texto legible para humanos, pero no aptos para análisis o informes. Este módulo cierra esa brecha convirtiendo los archivos de registro en bruto en un formato CSV estructurado que se integra con herramientas comunes como Excel, Power BI, bases de datos SQL y sistemas SIEM.

Principios clave de diseño:

  • Rendimiento primero — optimizado para archivos de más de 100MB usando E/S por streaming y operaciones con cadenas
  • Compatibilidad entre ediciones — soporta PowerShell Desktop (5.1+) y Core (7.x)
  • Listo para producción — incluye validación de encabezados, manejo de errores y compresión opcional
  • Compatible con pipeline — se integra naturalmente con la arquitectura de pipeline de PowerShell

Qué hay aquí

SecciónLéelo cuando
ResumenQuieras saber qué hace el módulo y si se ajusta a tu problema
Formatos de salidaNecesites entender qué significan las columnas CSV antes de diseñar un pipeline
Parámetros y opcionesEstés decidiendo qué interruptores necesita tu conversión
RendimientoTus registros sean grandes o la conversión sea más lenta de lo esperado
IntegraciónEstés cargando los resultados en Excel, Power BI, SQL, un SIEM o Python
Mejores prácticas operativasVayas a ejecutar esto sin supervisión en producción
Ejemplos de usoQuieras un escenario completo para adaptar
Solución de problemasAlgo no se comporte como esperas
Referencia de comandosNecesites la lista autorizada de parámetros

¿Nuevo en el módulo? Comienza con el Resumen.

Recursos

Contribuciones

Las contribuciones son bienvenidas. Si encuentras problemas, errores o tienes sugerencias para mejoras, por favor abre un issue o pull request en el repositorio de GitHub.

1 - Descripción general

Qué hace DNSServer.DebugLogParser, cómo es un registro de depuración de DNS en Windows, y cuándo vale la pena convertirlo a CSV.

Windows DNS Server puede escribir un registro de depuración. Es un archivo de texto plano, está pensado para ser leído por un humano, y crece cientos de megabytes al día en un controlador de dominio ocupado. Esa combinación lo hace casi inútil en el momento en que quieres responder una pregunta como "¿qué cliente pidió este dominio 40.000 veces anoche?"

DNSServer.DebugLogParser convierte ese archivo de texto en una tabla CSV. Una línea del registro se convierte en una fila con columnas nombradas, para que puedas abrirlo en Excel, cargarlo en Power BI, insertarlo masivamente en SQL Server o enviarlo a tu SIEM.

El módulo contiene un único comando:

Convert-DNSDebugLogFile -InputFile "C:\Windows\System32\dns\dns.log"

Ese es todo el punto de entrada. Todo lo demás en este sitio trata sobre hacerlo a escala, programado y en varios servidores.

Cómo es un registro de depuración DNS

Una entrada en bruto es una sola línea con campos posicionales, algunos de ellos entre corchetes:

2026-01-20 23:00:16 0FE0 PACKET 000002C53117D990 UDP Rcv 10.0.0.2 c049 Q [0001 D NOERROR] A (3)odc(9)officeapps(4)live(3)com(0)

Después de la conversión, el mismo evento es una fila CSV que puedes filtrar y ordenar:

DateTime;ThreadId;Context;PacketId;Protocol;Direction;ClientIP;Xid;Type;Opcode;FlagsHex;FlagsChar;ResponseCode;QuestionType;QuestionName;Information;Details;ComputerName
2026-01-20 23:00:16;0FE0;Packet;000002C53117D990;UDP;Rcv;10.0.0.2;c049;Query;Standard;0001;RecursionDesired;NOERROR;A;"odc.officeapps.live.com";"";"";dc01

Fíjate en dos cosas que el formato en bruto hace difíciles y que el parser maneja por ti:

  • El nombre consultado está almacenado en notación wire DNS, (3)odc(9)officeapps(4)live(3)com(0), y se convierte en un FQDN normal.
  • Un solo evento no siempre es una sola línea. Los bloques de detalle PACKET y los mensajes de evento continúan en líneas siguientes indentadas. El parser mantiene esos adjuntos al registro al que pertenecen en lugar de descartarlos o crear filas huérfanas.

Cada entrada lleva hasta 16 campos nativos — marca de tiempo, protocolo, dirección, IP del cliente, tipo de consulta, nombre consultado, código de respuesta, flags y más. La lista completa de columnas está descrita en Formatos de salida.

Por qué vale la pena convertir

Solución de problemas

  • Descubrir por qué un nombre no se resuelve y si la consulta siquiera llegó al servidor
  • Identificar clientes o aplicaciones mal configuradas que saturan el servidor
  • Rastrear de dónde viene realmente una consulta problemática
  • Verificar transferencias de zona y comportamiento general del DNS

Rendimiento y capacidad

  • Clasificar clientes por volumen de consultas y encontrar los ruidosos
  • Ver qué tipos de registros dominan tu tráfico
  • Detectar errores de configuración que causan búsquedas evitables
  • Monitorear la carga del servidor a lo largo del tiempo en lugar de adivinar

Análisis de seguridad

  • Detectar túneles DNS y exfiltración de datos (típicamente visible como tráfico excesivo de TXT — ver el ejemplo de análisis con SQL Server)
  • Encontrar consultas contra dominios de malware y comando y control
  • Reconocer patrones de consulta de un host comprometido
  • Vigilar abusos de amplificación DNS
  • Reconstruir qué ocurrió durante un incidente

Cumplimiento y auditoría

  • Cumplir con obligaciones de registro y retención
  • Mantener un rastro de auditoría de la actividad de red
  • Generar informes para gerencia o auditores

Cómo funciona el módulo

Convert-DNSDebugLogFile lee el registro como un flujo y escribe el CSV como un flujo. El archivo nunca se carga completo en memoria, así que un registro de 100 MB consume aproximadamente la misma RAM que uno de 10 MB. Los detalles están en Rendimiento.

Lo que te ofrece:

CapacidadDetalle
Diseño CSV consistente18 columnas, mismo orden siempre, sin importar qué contextos aparezcan en el registro
Registros multilíneaLos bloques de detalle PACKET y el texto del evento permanecen adjuntos a su registro
Versiones de DNS ServerFormatos de registro desde 2012 R2 hasta 2025
Ediciones de PowerShellWindows PowerShell 5.1+ y PowerShell 7.x
Tamaño de archivoProbado con registros de más de 100 MB; procesamiento en un solo paso
Validación de encabezadoRechaza archivos que no son registros de depuración DNS (se puede desactivar)
EstadísticasResúmenes diarios opcionales, por contexto y por cliente/protocolo/tipo
Soporte para pipelineGet-ChildItem *.log | Convert-DNSDebugLogFile
CompresiónSalida ZIP opcional, típicamente 90 % más pequeña
Limpieza de origenEliminación opcional del registro tras ejecución exitosa
Registros internacionalesAnaliza y escribe fechas según cultura, para que un registro de-DE se pueda leer en una estación en-US
Rutas de redLee fuentes desde rutas SMB/UNC
Archivos bloqueadosLee registros que DNS Server (o cualquier otro) tiene abiertos actualmente

Registro activo vs. registro rotado

El patrón práctico es habilitar la rotación de registros en el servidor DNS y dejar que la conversión programada omita el archivo más nuevo:

Get-ChildItem "C:\Administration\Logs\DNSServer\*.log" |
    Sort-Object LastWriteTime -Descending |
    Select-Object -Skip 1 |
    Convert-DNSDebugLogFile -ComputerName $env:COMPUTERNAME

Una implementación completa basada en directivas de grupo está documentada en el ejemplo de recopilación guiada por GPO.

Qué ver a continuación

Licencia y soporte

Licencia MIT. El soporte comunitario se realiza a través de GitHub Issues; se aceptan reportes de errores y solicitudes de funciones.

2 - Formatos de salida

Las columnas del archivo de datos CSV, los dos archivos opcionales de estadísticas y ejemplos reales de salida que puedes abrir antes de ejecutar cualquier cosa.

Convert-DNSDebugLogFile genera hasta tres archivos por cada registro de entrada:

ArchivoContieneSe crea cuando
<name>.csvUna fila por cada entrada de registro analizada-OutputType CSV o Both
<name>_Statistic.csvConteo diario de registros por contexto-OutputType Statistic o Both
<name>_PacketStatistic.csvConteo diario de consultas por cliente, protocolo, dirección y tipo de registro-OutputType Statistic o Both

Both es el valor predeterminado. La salida se guarda junto al archivo de entrada a menos que configures -OutputFile.

Los archivos de ejemplo enlazados en esta página son resultados reales de conversiones, no simulaciones. Descarga uno y ábrelo en Excel antes de decidir el diseño de tu pipeline.

El archivo de datos CSV

Ejemplo de salida:

LocalidadColumna DetallesArchivos
en-USno pobladaWithComputerName, NoComputerName
de-DEno pobladaWithComputerName, NoComputerName
de-DEpobladaWithComputerName, NoComputerName

Dos filas de una conversión real — una consulta DNS y una nota interna del servidor:

DateTime;ThreadId;Context;PacketId;Protocol;Direction;ClientIP;Xid;Type;Opcode;FlagsHex;FlagsChar;ResponseCode;QuestionType;QuestionName;Information;Details;ComputerName
2026-01-20 23:00:16;0FE0;Packet;000002C53117D990;UDP;Rcv;10.0.0.2;c049;Query;Standard;0001;RecursionDesired;NOERROR;A;"odc.officeapps.live.com";"";"";dc01
2026-01-20 23:00:16;DF0;Note;;;;;;;;;;;;"";"got GQCS failure on a dead socket context status=995, socket=904";"";dc01

Columnas

Siempre 18 columnas, siempre en este orden:

#ColumnaSignificadoUso típico
1DateTimeMarca temporal de la entradaFiltrado por tiempo, unión con otros registros
2ThreadIdHilo de trabajo del servidor DNSRara vez necesario; útil para correlacionar problemas internos del servidor
3ContextTipo de entrada: Packet, Event, Note, DSPoll, Init, Lookup, Recurse, Remote, TombstonePrimer filtro que aplicarás — Packet es el tráfico DNS real
4PacketIdIdentificador interno del paqueteEmparejar una consulta con su respuesta
5ProtocolUDP o TCPPicos en TCP pueden indicar respuestas grandes o transferencias de zona
6DirectionRcv (consulta recibida) o Snd (servidor respondió)Separar volumen de solicitudes del volumen de respuestas
7ClientIPDirección del host que consultaAnálisis de los que más consultan, delimitación de incidentes
8XidID de transacción DNS (hexadecimal)Emparejar solicitud y respuesta
9TypeQuery o Response
10OpcodeStandard, Notify, Update, UnknownSepara actualizaciones dinámicas y notificaciones de zona de las consultas normales
11FlagsHexBanderas del encabezado en bruto (hexadecimal)Para análisis profundo del protocolo
12FlagsCharBanderas decodificadas: Authoritative, Truncated, RecursionDesired, RecursionAvailableVersión legible de lo anterior
13ResponseCodeNOERROR, NXDOMAIN, SERVFAIL, …Reporte de tasa de errores, búsqueda de fallos en resolución
14QuestionTypeTipo de registro: A, AAAA, MX, PTR, TXT, …El volumen de TXT es un indicador clásico de túneles
15QuestionNameNombre consultado como un FQDN normalCoincidencia con inteligencia de amenazas, informes de dominios principales
16InformationTexto libre para entradas Event / Note; para bloques de detalle Packet la línea de encabezado TCP/UDPLectura de mensajes del servidor
17DetailsRepresentación JSON de un bloque de detalle Packet; vacío en otro casoInspección completa del paquete sin volver al registro en bruto
18ComputerNameServidor origen, desde -ComputerNameMantener conjuntos de datos multi-servidor atribuibles

Dos cosas para planificar:

  • No todas las columnas se llenan en cada fila. Solo las entradas Packet tienen IP del cliente, nombre de consulta y código de respuesta. Las filas Note y Event llevan su texto en Information y dejan vacías las columnas de protocolo. Diseña tu esquema de base de datos y filtros de panel en consecuencia.
  • ComputerName siempre es la última columna, incluso si no usas -ComputerName. Entonces simplemente está vacía. Esto mantiene el diseño idéntico en todos los servidores para que puedas concatenar archivos de muchos servidores DNS sin un paso de mapeo de columnas.

La columna Detalles

Los bloques de detalle solo aparecen si el servidor DNS está configurado para registrar detalles completos del paquete. Cuando existen, el analizador los convierte en un único valor JSON para que la fila siga siendo una sola:

{
  "Socket": "848",
  "Remote": "addr 10.10.0.11, port 60580",
  "Buflength": "0x10000 (65536)",
  "Message": {
    "XID": "0x0001",
    "OPCODE": "0 (QUERY)",
    "RCODE": "0 (NOERROR)",
    "QUESTION": [ { "Name": "berlin.de", "QTYPE": "A (1)", "QCLASS": "1" } ],
    "ANSWER": []
  }
}

Analizar estos bloques consume tiempo y hace que el CSV sea considerablemente más grande. Si no los necesitas, usa -NoDetailsParsing: la columna permanece presente pero vacía, y la conversión es más rápida. Consulta Rendimiento.

Los archivos de estadísticas

Las estadísticas son agregados diarios. Úsalas cuando quieras una tendencia o un resumen y no quieras mover el conjunto completo de registros — son órdenes de magnitud más pequeñas que el archivo de datos.

Estadísticas por contexto (*_Statistic.csv)

Responde: ¿cuánto de qué tipo de actividad ocurrió por día?

Date;Context;Count;ComputerName
2026-01-20;Event;2;dc01
2026-01-20;Note;2;dc01
2026-01-20;Packet;12;dc01
ColumnaSignificado
DateDía, siempre en formato yyyy-MM-dd
ContextNombre del contexto (Packet, Event, Note, …)
CountNúmero de registros de ese contexto en ese día
ComputerNameServidor origen

Archivos de ejemplo: en-US WithComputerName, en-US NoComputerName, de-DE WithComputerName, de-DE NoComputerName

Estadísticas de paquetes (*_PacketStatistic.csv)

Responde: ¿quién consultó qué, con qué frecuencia, por día?

Date;ClientIP;Protocol;Direction;QuestionType;Count;ComputerName
2026-01-20;10.0.0.1;UDP;Rcv;A;3;dc01
2026-01-20;10.0.0.1;UDP;Snd;A;3;dc01
2026-01-20;10.0.0.2;UDP;Rcv;A;3;dc01
ColumnaSignificado
DateDía, siempre en formato yyyy-MM-dd
ClientIPHost que consulta
ProtocolUDP o TCP
DirectionRcv o Snd
QuestionTypeTipo de registro DNS
CountNúmero de paquetes coincidentes ese día
ComputerNameServidor origen

Archivos de ejemplo: en-US WithComputerName, en-US NoComputerName, de-DE WithComputerName, de-DE NoComputerName

Delimitador y formato de fecha

Ambos tipos de salida respetan -Delimiter (por defecto ;) y -OutputCulture. Para cualquier cosa que será importada por una máquina, escribe marcas temporales tipo ISO:

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputCulture 'sv-SE'

Esto produce 2026-01-20 23:00:16, que SQL Server, Power BI y pandas leen sin necesidad de indicar formato. Más detalles en Parámetros y opciones.

3 - Parámetros y Opciones

Qué cambia realmente cada opción de Convert-DNSDebugLogFile, cuándo la necesitas y las trampas en las que es fácil caer.

Esta página explica las opciones en lenguaje sencillo y en el orden en que normalmente las necesitarás. Es una guía, no una especificación: la lista autoritativa y siempre actualizada de parámetros está en la referencia del comando y en:

Get-Help Convert-DNSDebugLogFile -Full

La versión corta

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log"

Esa sola línea ya te da un comportamiento sensato: archivos de datos y estadísticas, delimitador punto y coma, formato de fecha de tu máquina, validación de encabezado activada, registro fuente sin tocar. Todo lo que sigue es ajuste fino.

OpciónPredeterminadoCámbialo cuando
-InputFile(requerido)siempre
-OutputFileruta de entrada con .csvquieres la salida en otro lugar
-Delimiter;tu consumidor espera coma, tabulador o barra vertical
-ComputerNamevacíocombinas registros de más de un servidor
-OutputTypeBothsolo quieres datos, o solo resúmenes
-ContextFilterAllsolo te interesa el tráfico DNS real
-InputCulturecultura actualel registro proviene de un servidor con otra configuración regional
-OutputCulturecultura actualuna máquina leerá el CSV
-NoDetailsParsingdesactivadoimporta más el rendimiento que los detalles de los paquetes
-CompressOutputdesactivadoarchivas o transfieres los resultados
-RemoveSourceFiledesactivadolimpieza programada y confías en la salida
-SkipHeaderValidationdesactivadoel archivo es válido pero el encabezado es inusual

Entrada y salida

-InputFile

Ruta al registro que se va a convertir. Acepta un arreglo y entrada por canalización — por eso funciona esto:

Get-ChildItem "C:\Administration\Logs\DNSServer\*.log" | Convert-DNSDebugLogFile

Get-ChildItem emite objetos con una propiedad FullName, y -InputFile la acepta por nombre de propiedad (sus alias incluyen FullName, Path, FilePath). No se necesita ForEach-Object.

Funcionan rutas locales y rutas SMB/UNC:

Convert-DNSDebugLogFile -InputFile "\\dc01\C$\Administration\Logs\DNSServer\dns.log"

El comando también puede abrir un registro que el servidor DNS tiene abierto actualmente. Consulta registros activos abajo antes de confiar en eso.

-OutputFile

Sin esta opción, el CSV se guarda junto al archivo de entrada, con el mismo nombre base y extensión .csv. Con ella, controlas el destino.

-Delimiter

El valor predeterminado es punto y coma, porque en regiones donde la coma es el separador decimal, eso es lo que Excel espera. Usa -Delimiter "," para herramientas y bases de datos que asumen valores separados por comas clásicas, o -Delimiter "`t" para tabulador.

Sea cual sea tu elección, usa el mismo valor en el lado de importación. Un desajuste es la causa número uno de que “todo termine en una sola columna”.

Etiquetado y filtrado

-ComputerName

Llena la columna ComputerName. La columna existe de todas formas; esto solo le da un valor.

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -ComputerName $env:COMPUTERNAME

Siempre configúralo cuando varios servidores alimentan un conjunto de datos — de lo contrario no podrás saber después de qué DC proviene una fila.

-OutputType

  • CSV — solo archivo de datos
  • Statistic — solo los dos archivos agregados, sin datos a nivel de fila
  • Both — los tres archivos (predeterminado)

Statistic es la opción rápida y pequeña cuando solo necesitas tendencias diarias. CSV es adecuado cuando un sistema posterior hace su propia agregación.

-ContextFilter

Un registro de depuración DNS mezcla tráfico real de consultas con charlas internas del servidor. -ContextFilter decide qué pasa a la salida.

# solo tráfico DNS real
Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -ContextFilter Packet

# tráfico más eventos del servidor, pero sin notas de diagnóstico
Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -ContextFilter Packet, Event
ValorContiene
Alltodo (predeterminado)
Packetconsultas y respuestas DNS — los datos que la mayoría de análisis necesitan
Eventeventos del servidor, p. ej. “El servidor DNS ha iniciado”
Notenotas y advertencias de diagnóstico, p. ej. errores de socket

Tipos de contexto adicionales (DSPoll, Init, Lookup, Recurse, Remote, Tombstone) aparecen bajo All.

Filtrar solo a Event o Note llena solo DateTime, ThreadId, Context e Information — las columnas de protocolo quedan vacías porque esas entradas simplemente no llevan esa información.

-ContextFilter Packet es la elección habitual para pipelines de seguridad e informes: elimina el ruido y reduce notablemente la salida.

Registros internacionales

El servidor DNS escribe marcas de tiempo en la configuración regional de Windows de la máquina donde corre. Un DC alemán escribe 20.01.2026 23:00:16; un servidor de EE. UU. escribe 1/20/2026 11:00:16 PM. Si la configuración regional de tu estación de trabajo difiere de la del servidor, el análisis falla — o peor, intercambia día y mes silenciosamente.

-InputCulture

Indica al analizador qué configuración regional usa el registro fuente:

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns-berlin.log" -InputCulture 'de-DE'
CulturaFormato de marca de tiempo en el registro
de-DEDD.MM.YYYY HH:MM:SS
en-USM/D/YYYY H:MM:SS AM/PM
en-GBDD/MM/YYYY HH:MM:SS
sv-SEYYYY-MM-DD HH:MM:SS

El valor predeterminado es la cultura de la sesión que ejecuta el comando. En un entorno con configuraciones regionales mixtas, configúralo explícitamente en lugar de confiar en ese valor predeterminado — y recuerda que una tarea programada que corre como SYSTEM puede no tener la cultura con la que probaste interactivamente.

-OutputCulture

Controla cómo se escriben las marcas de tiempo en el CSV:

# salida tipo ISO que SQL Server, Power BI y pandas entienden
Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputCulture 'sv-SE'

# mismo efecto, cultura invariante explícita
Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" `
    -OutputCulture ([System.Globalization.CultureInfo]::InvariantCulture)

Regla general: si un humano abre el archivo en Excel, usa la cultura local. Si una máquina lo lee, usa sv-SE o cultura invariante y olvídate de configuraciones regionales en la importación.

Los dos parámetros son independientes — puedes leer un registro sueco y escribir una salida con formato estadounidense.

Velocidad y almacenamiento

-NoDetailsParsing

Si el servidor DNS registra detalles completos de paquetes, el analizador convierte cada bloque de detalles en JSON en la columna Details. Eso es útil, pero también la parte más costosa de la ejecución y hace que el CSV crezca.

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -NoDetailsParsing

La columna permanece presente pero vacía; la línea de encabezado de detalles TCP/UDP sigue disponible en Information. En registros con muchos bloques de detalles esto puede reducir el tiempo de procesamiento entre un 30 y 50 %. Úsalo cuando la información a nivel de consulta sea suficiente.

-CompressOutput

Comprime los archivos CSV generados y elimina los sin comprimir. dns.log produce dns.zip en lugar de dns.csv.

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -CompressOutput

Un CSV de esta forma típicamente se comprime un 90 % o más, así que esto es un ahorro de almacenamiento casi gratis para archivos de archivo y para enviar archivos por la red.

-RemoveSourceFile

Elimina el archivo fuente .log tras una conversión exitosa — el registro solo se borra si todos los archivos de salida se crearon.

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -CompressOutput -RemoveSourceFile

Redes de seguridad

-SkipHeaderValidation

Por defecto el comando verifica que el archivo realmente sea un registro de depuración del servidor DNS antes de analizarlo. Esto evita el error clásico de apuntar el trabajo a la carpeta equivocada.

Desactívalo solo para casos genuinamente inusuales: registros editados a mano, extractos prefiltrados, formatos personalizados. Manténlo activado en todos los demás casos — es barato y es lo que evita que un error tipográfico produzca un montón de filas basura.

-WhatIf y -Confirm

El comando soporta ambos. -WhatIf es la forma correcta de ver qué tocaría un nuevo trabajo por lotes:

Get-ChildItem "C:\Administration\Logs\DNSServer\*.log" |
    Convert-DNSDebugLogFile -RemoveSourceFile -WhatIf

-Confirm pregunta antes de procesar cada archivo, antes de eliminar un archivo fuente y antes de sobrescribir una salida existente.

Registros activos

Convert-DNSDebugLogFile puede leer un archivo que el servidor DNS tiene abierto. Útil para echar un vistazo rápido a lo que está pasando ahora mismo.

Poniéndolo todo junto

Una invocación típica en producción en un controlador de dominio:

Get-ChildItem "C:\Administration\Logs\DNSServer\*.log" |
    Sort-Object LastWriteTime -Descending |
    Select-Object -Skip 1 |
    Convert-DNSDebugLogFile `
        -ComputerName $env:COMPUTERNAME `
        -Delimiter ';' `
        -OutputType Both `
        -ContextFilter Packet `
        -OutputCulture 'sv-SE' `
        -CompressOutput

Se lee así: toma cada registro rotado excepto el activo, conserva solo el tráfico DNS, etiqueta cada fila con el nombre del servidor, escribe marcas de tiempo legibles por máquina y deja archivos comprimidos. La versión completa para tarea programada y directiva de grupo está en el ejemplo de recopilación dirigida por GPO.

4 - Rendimiento

Cómo el analizador maneja logs de 100 MB sin consumir la memoria de tu servidor, y qué puedes hacer para mantener las conversiones rápidas.

Los logs de depuración DNS en un controlador de dominio ocupado son grandes. Convert-DNSDebugLogFile está diseñado para ese caso: ha sido probado con logs de 100 MB y más, y los procesa en minutos en hardware de servidor común.

Por qué es rápido

No necesitas saber esto para usar el módulo, pero explica el comportamiento que observarás.

TécnicaEfecto que notarás
StreamReader / StreamWriter con buffers de 64 KBEl archivo se lee y escribe en fragmentos en lugar de un gran Get-Content
Transmisión, pasada únicaEl uso de memoria se mantiene aproximadamente constante sin importar el tamaño del log
Operaciones con cadenas (.Substring(), .IndexOf()) en lugar de expresiones regularesMucho menos CPU por línea, y hay millones de líneas
CSV escrito a mano en lugar de Export-CsvSin sobrecarga de pipeline de objetos por registro
Agregación basada en tabla hash para estadísticasLos resúmenes cuestan casi nada extra durante la misma pasada

La consecuencia importante: el log completo nunca se mantiene en memoria. Un log de 500 MB no necesita 500 MB de RAM. Esta es la diferencia entre el módulo y el enfoque de “leer el archivo, dividirlo, construir objetos” que la mayoría de los scripts caseros usan — ese enfoque funciona bien con una muestra de 5 MB y falla en un DC real.

Cómo sacar el máximo provecho de una ejecución

Convierte fragmentos rotados, no un archivo gigante

Configura el Servidor DNS para que rote el log a un tamaño manejable — entre 50 y 200 MB es un buen rango. Varios archivos medianos se convierten en un tiempo predecible y permiten que un trabajo programado termine dentro de su ventana. Un archivo que crece sin parar eventualmente no.

La rotación también te da archivos cerrados con los que trabajar, que es lo que quieres de todos modos:

Get-ChildItem "C:\Administration\Logs\DNSServer\*.log" |
    Sort-Object LastWriteTime -Descending |
    Select-Object -Skip 1 |
    Convert-DNSDebugLogFile -ComputerName $env:COMPUTERNAME

Omite el análisis de detalles cuando no lo necesites

Si el servidor DNS escribe detalles completos de paquetes, convertir esos bloques a JSON es la parte más costosa de la conversión.

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -NoDetailsParsing

Espera ejecuciones un 30–50 % más rápidas en logs que contienen muchos bloques de detalle, además de un CSV mucho más pequeño. Aún obtienes los datos a nivel de consulta y la línea de encabezado de detalle TCP/UDP en Information. Consulta Parámetros y Opciones.

Filtra temprano

-ContextFilter Packet descarta notas y eventos del servidor antes de que se escriban. Menos salida significa menos E/S, archivos más pequeños y menos trabajo posterior.

Pide solo lo que necesitas

-OutputType Statistic omite por completo la escritura del CSV a nivel de fila. Si tu panel solo muestra conteos diarios, esta es con diferencia la opción más económica.

Convierte localmente, mueve los resultados

El módulo lee rutas SMB/UNC, pero transferir un log bruto de 200 MB por la red para analizarlo centralmente es la forma lenta. Convierte en el servidor DNS y luego mueve el CSV (comprimido), que suele ser una décima parte de los bytes. Este es el diseño detrás del ejemplo de recopilación impulsada por GPO.

Comprime para transferencia y archivo

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -CompressOutput

Un CSV de esta forma típicamente se reduce en un 90 % o más. La compresión cuesta un poco de CPU al final de la ejecución y ahorra mucho espacio en disco y red después.

Cuando una ejecución es más lenta de lo esperado

Revisa estos puntos en orden:

  1. Disco, no CPU. La conversión es intensiva en E/S. Un log en un volumen ocupado, o leído por un enlace lento, domina el tiempo de ejecución.
  2. Bloques de detalle. Si el log contiene detalles completos de paquetes y no usaste -NoDetailsParsing, ahí se va el tiempo.
  3. Tamaño del archivo. Un log único de varios gigabytes tardará un rato de todas formas. Soluciona esto con rotación, no con parámetros.
  4. Antivirus. El escaneo en tiempo real tanto del log fuente como del CSV generado puede duplicar el costo efectivo de E/S. Una exclusión para el directorio del log es una medida común y razonable.
  5. Presión de memoria. El módulo usa streaming, así que no debería ser la causa — pero un servidor que ya está intercambiando hará que todo sea lento.

Más síntomas y soluciones están recopilados en Solución de problemas.

5 - Integración con Herramientas de Análisis

Llevar el CSV convertido a Excel, Power BI, SQL Server, un SIEM o un cuaderno de Python — incluyendo la configuración del delimitador y la fecha que hacen que funcione a la primera.

El objetivo de convertir un registro de depuración DNS es lo que sucede después. Se eligió CSV porque todo lo lee — pero “todo lee CSV” oculta dos configuraciones que deciden si una importación es sencilla o una tarde de ajustes.

Dos configuraciones que lo deciden todo

Delimitador. El valor predeterminado es ;. Mantenlo para Excel en configuraciones regionales que usan la coma como separador decimal. Cambia a , para la mayoría de bases de datos y herramientas de ciencia de datos. Sea cual sea tu elección, informa lo mismo al lado que importa.

Formato de fecha. -OutputCulture controla cómo se escriben las marcas de tiempo. Para cualquier cosa leída por una máquina, usa sv-SE (o cultura invariable) para que DateTime salga como 2026-01-20 23:00:16:

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputCulture 'sv-SE'

Todos los consumidores a continuación entienden ese formato sin necesidad de indicaciones. La salida específica de la configuración regional como 20.01.2026 se importará como texto o, peor aún, se interpretará mal como mes/día.

Microsoft Excel

La forma más rápida de ver un registro convertido individual.

  • Con el delimitador predeterminado ; y una configuración regional que lo espera, un doble clic abre el archivo con columnas correctas.
  • Si todo cae en la columna A, el delimitador no coincide con la configuración de tu Excel. Vuelve a ejecutar con -Delimiter "," o importa vía Datos → Desde texto/CSV y elige el delimitador ahí.
  • Convierte el rango en una tabla (Ctrl+T) y crea una tabla dinámica con ClientIP, QuestionName o QuestionType. Los principales clientes y dominios se obtienen en un minuto.
  • Para cualquier cosa con más de unos cientos de miles de filas, usa Power Query o alguna de las otras opciones abajo.

Los archivos *_Statistic.csv y *_PacketStatistic.csv suelen ser mejores para Excel — están preagregados y se mantienen pequeños. Consulta Formatos de Salida.

Power BI

Importa los archivos CSV y crea paneles para actividad DNS, principales clientes, tendencias de consultas y tasas de error.

  • Apunta Power Query a la carpeta que contiene tus archivos convertidos en lugar de a un solo archivo. El formato es idéntico entre servidores y días, así que los archivos simplemente se agregan.
  • La columna ComputerName es lo que hace posible un informe multi-servidor — configura -ComputerName durante la conversión o no podrás filtrar por servidor.
  • ResponseCode y QuestionType son filtros naturales; DateTime se convierte en tu eje temporal.
  • Alimentar Power BI con *_PacketStatistic.csv en lugar del archivo completo mantiene el modelo pequeño cuando solo necesitas tendencias diarias.

Bases de datos SQL

Carga masiva del CSV en SQL Server, PostgreSQL o cualquier otro que hable SQL, para retención a largo plazo y consultas repetibles.

Un recorrido listo para ejecutar — definición de tabla, conversión, importación con SqlBulkCopy y una consulta para detectar actividad sospechosa TXT — está documentado en Flujo de Trabajo de Análisis de Seguridad con SQL Server.

Puntos a planificar antes de la primera carga:

  • Usa -OutputCulture 'sv-SE' para que las marcas de tiempo caigan en una columna datetime2 sin trucos de conversión.
  • Information y Details pueden ser largos; asígnales nvarchar(max).
  • Indexa lo que realmente consultas — típicamente DateTime, ClientIP y QuestionName.
  • Mantén -ComputerName poblado para que las filas sigan siendo atribuibles después de fusionarlas.

Sistemas SIEM

Splunk, Elastic, Sentinel y plataformas similares ingieren el CSV para correlacionar con otra telemetría de seguridad y para alertas.

  • Envía la salida comprimida (-CompressOutput) — es aproximadamente una décima parte del tamaño y la mayoría de los recolectores la descomprimen solos.
  • Define el mapeo de campos una vez; el formato de columnas nunca cambia entre ejecuciones o servidores, incluyendo la columna ComputerName siempre presente al final.
  • Haz que tu recolector deduplique o archive los archivos .log procesados. Un trabajo de conversión que reprocesa los mismos logs rotados volverá a enviar filas idénticas.
  • -ContextFilter Packet mantiene bajo el volumen de ingestión (y el costo de licencia) cuando las notas del servidor no forman parte de tus casos de uso.

Python, R y herramientas de ciencia de datos

La salida estructurada está lista para detección de anomalías, establecimiento de líneas base y análisis personalizados.

import pandas as pd

df = pd.read_csv(
    r"C:\Administration\Logs\DNSServer\dns.csv",
    sep=";",
    parse_dates=["DateTime"],
)

# top 20 nombres consultados, solo consultas
top = (
    df[df["Direction"] == "Rcv"]
    .groupby("QuestionName")
    .size()
    .sort_values(ascending=False)
    .head(20)
)
print(top)

parse_dates funciona directamente cuando exportas con -OutputCulture 'sv-SE'. Desde aquí, pandas, scikit-learn o R manejan clustering, estacionalidad y detección de valores atípicos como de costumbre.

Quedarse en PowerShell

No tienes que salir de PowerShell para una respuesta rápida:

$dns = Import-Csv "C:\Administration\Logs\DNSServer\dns.csv" -Delimiter ';'

# clientes más ruidosos
$dns | Where-Object Direction -eq 'Rcv' |
    Group-Object ClientIP |
    Sort-Object Count -Descending |
    Select-Object -First 10 Count, Name

# búsquedas fallidas
$dns | Where-Object ResponseCode -eq 'NXDOMAIN' |
    Group-Object QuestionName |
    Sort-Object Count -Descending |
    Select-Object -First 10 Count, Name

Import-Csv lee todo el archivo en memoria, así que esto está bien para un fragmento rotado y no es adecuado para una exportación de varios gigabytes — para eso están las rutas de base de datos y SIEM.

6 - Mejores prácticas operativas

Qué hacer bien antes de dejar que una conversión de registros DNS se ejecute sin supervisión en controladores de dominio en producción.

Convertir un registro manualmente es fácil. Ejecutarlo cada noche en cada controlador de dominio, durante años, sin que nadie lo revise, es la parte que requiere un poco de diseño. Estos son los puntos que importan en la práctica.

1. Convierte los registros rotados, no el activo

Habilita la rotación de registros en el servidor DNS y convierte solo los archivos cerrados. El módulo puede leer el registro que el servidor DNS está escribiendo actualmente, pero ese archivo cambia durante la conversión: las entradas más recientes pueden faltar y el último registro puede estar truncado. Dos ejecuciones producen dos resultados diferentes.

El patrón estándar omite el archivo más nuevo:

Get-ChildItem "C:\Administration\Logs\DNSServer\*.log" |
    Sort-Object LastWriteTime -Descending |
    Select-Object -Skip 1 |
    Convert-DNSDebugLogFile -ComputerName $env:COMPUTERNAME

Compromiso a tener en cuenta: en un servidor de bajo volumen, la rotación puede tardar más de un día, por lo que los datos del día actual permanecen sin convertir hasta que el archivo rote. Ajusta el umbral de rotación en consecuencia.

2. Programa la tarea y dale una identidad que funcione

El Programador de tareas es el lugar habitual para esto — diario es un valor predeterminado sensato. Una implementación completa de Directiva de Grupo para controladores de dominio está documentada en el ejemplo de recopilación impulsada por GPO, y una tarea independiente en el ejemplo de tarea programada.

Tres cosas suelen causar problemas aquí:

  • Descubrimiento del módulo. Una tarea que se ejecuta como SYSTEM con -NoProfile solo ve las rutas de módulos a nivel máquina. Instala el módulo a nivel máquina o añade un Import-Module explícito en la acción de la tarea.
  • Cultura. La cuenta que ejecuta la tarea puede no tener la configuración regional con la que probaste interactivamente. Establece -InputCulture y -OutputCulture explícitamente en lugar de confiar en el valor predeterminado.
  • Acceso a la red. Si la fuente o el destino es una ruta UNC, SYSTEM se autentica como la cuenta del equipo. Concede permisos de compartición y NTFS a la cuenta del equipo (o al grupo Domain Controllers), o ejecuta la tarea como una cuenta de servicio dedicada.

3. Rota a un tamaño que puedas procesar

50–200 MB por archivo mantiene las conversiones predecibles y permite que una tarea nocturna termine dentro de su ventana. Un archivo que crece indefinidamente eventualmente no lo hace. Consulta Rendimiento.

4. Valida las primeras salidas antes de automatizar

Ejecuta la conversión manualmente en dos o tres registros reales y abre el CSV:

  • ¿Son correctas las marcas de tiempo — no están intercambiados día/mes? (Si lo están, configura -InputCulture.)
  • ¿El delimitador coincide con lo que espera tu consumidor?
  • ¿Está ComputerName poblado?
  • ¿Están presentes los contextos que necesitas y filtrados los que no?

-WhatIf te muestra qué archivos tocaría un lote antes de tocarlos:

Get-ChildItem "C:\Administration\Logs\DNSServer\*.log" |
    Convert-DNSDebugLogFile -RemoveSourceFile -WhatIf

5. Decide qué hacer con los registros procesados

Una tarea que simplemente convierte “todos los registros excepto el más nuevo” reprocesará los mismos archivos cada noche. Eso es robusto y simple, pero sobrescribe las salidas y puede insertar filas duplicadas en quien las consuma.

Elige una opción:

  • mover los archivos .log procesados a una carpeta de archivo
  • eliminarlos con -RemoveSourceFile una vez que confíes en la canalización
  • hacer que el recolector posterior deduplique

Cualquiera que elijas, anótalo — este es el detalle que confunde al siguiente administrador.

6. Planifica almacenamiento y retención

La compresión (-CompressOutput) suele reducir el CSV en un 90 % o más, pero el volumen sigue acumulándose. Estima según tu tasa real de consultas y tu obligación de retención, y establece una fecha límite para los datos en lugar de dejarlos crecer indefinidamente.

-OutputType Statistic vale la pena considerarlo para retenciones largas: los resúmenes diarios son pequeños y a menudo responden las preguntas de tendencia para las que se mantenían los datos a nivel de fila antiguos.

7. Trata la salida como sensible

Los registros DNS analizados describen tu estructura interna de nombres y quién consultó qué. Eso es más revelador que la mayoría de los registros de infraestructura y, dependiendo de tu jurisdicción, puede considerarse dato personal.

  • Restringe los permisos NTFS y de compartición en las carpetas de salida.
  • No dejes CSVs en un recurso compartido de archivos general “temporalmente”.
  • Incluye los datos de registros DNS en tu política de retención y eliminación, no solo en la de respaldo.
  • La salida comprimida es más pequeña, no protegida — usa cifrado o control de acceso donde importe.

8. Mantén la validación de encabezados activada

La comprobación predeterminada de que un archivo realmente es un registro de depuración DNS no cuesta nada y evita que una ruta mal escrita produzca miles de filas sin sentido. Usa -SkipHeaderValidation solo para formatos genuinamente inusuales — y ten en cuenta que el comando se niega a combinarlo con -RemoveSourceFile por esta misma razón.

9. Supervisa la tarea, no solo el servidor

Una conversión sin supervisión que se detiene silenciosamente es peor que no tener conversión, porque la brecha solo se nota cuando alguien necesita los datos.

  • Vigila la salida de error distinta de cero; la implementación de referencia con GPO lanza deliberadamente error cuando $Error.Count -gt 0 para que la tarea reporte fallo.
  • Alerta sobre el código de resultado de la última ejecución de la tarea programada, no solo sobre si la tarea existe.
  • Verifica que los archivos de salida realmente aparezcan con marcas de tiempo recientes.
  • Vigila el espacio libre en disco tanto en el volumen de registros como en el destino de salida.

Las causas comunes de una ejecución fallida — acceso denegado, registros corruptos, encabezados inválidos — se cubren en Solución de problemas.

10. Documenta el flujo de trabajo

Dónde se escriben los registros, cuándo se ejecuta la tarea, qué parámetros se usan, a dónde va la salida, quién la consume y cuánto tiempo se conserva. Seis líneas en tu wiki de operaciones. Eso es lo que hace que la configuración sea auditable y transferible.

7 - Solución de problemas

Síntomas que probablemente encontrarás al convertir registros de depuración DNS, qué los causa y cómo solucionarlos.

“El archivo no es un archivo válido de registro de depuración DNS”

La verificación del encabezado rechazó la entrada. Normalmente la ruta está simplemente equivocada: un archivo .log en la misma carpeta que no es el registro de depuración DNS, o un archivo que solo contiene un encabezado rotado.

Sigue estos pasos:

  1. Abre el archivo. Un registro de depuración DNS comienza con una línea de encabezado como Message logging started at … y continúa con entradas de consultas con marcas de tiempo.

  2. Confirma que el registro de depuración DNS está realmente habilitado y escribiendo en la ruta que esperas:

    Get-DnsServerDiagnostics | Select-Object Enable, LogFilePath, MaxMBFileSize
    
  3. Si el archivo es genuinamente un registro DNS pero el encabezado es inusual — editado a mano, prefiltrado, una exportación personalizada — omite la verificación:

    Convert-DNSDebugLogFile -InputFile "C:\Logs\odd.log" -SkipHeaderValidation
    

Mantén la validación habilitada en todos los demás casos. Ten en cuenta que -SkipHeaderValidation no puede combinarse con -RemoveSourceFile, por lo que un archivo no verificado nunca puede ser eliminado por la conversión.

El archivo de salida está vacío o tiene muchas menos filas de las esperadas

Verifica, en este orden:

  • ¿El registro contiene entradas de consultas? Un registro recién rotado puede contener solo un encabezado si aún no ocurrieron consultas.
  • ¿Se está usando un -ContextFilter? -ContextFilter Packet elimina por diseño las entradas Event y Note. Si filtraste a Event o Note, la mayoría de las columnas también estarán vacías — esos tipos de entradas solo contienen DateTime, ThreadId, Context e Information.
  • ¿Estaba activo el registro fuente? Un archivo que el servidor DNS sigue escribiendo puede cambiar durante la conversión; las entradas más nuevas pueden faltar y el último registro puede estar truncado. Convierte un registro rotado y cerrado cuando necesites una salida completa.
  • ¿Está el archivo corrupto o truncado? Revisa el final del registro en busca de una línea medio escrita.

Las fechas están mal, desplazadas o el día y el mes están intercambiados

El registro fue escrito por un servidor con una configuración regional de Windows diferente a la sesión que hace la conversión. 20.01.2026 y 01/20/2026 describen el mismo momento, pero solo si ambos lados coinciden en el formato.

# el registro provino de un servidor alemán
Convert-DNSDebugLogFile -InputFile "C:\Logs\dns-berlin.log" -InputCulture 'de-DE'

Establece -InputCulture explícitamente en trabajos programados en lugar de confiar en la cultura de la cuenta que los ejecuta. Si la salida debe ser legible por máquina, añade -OutputCulture 'sv-SE'. Más detalles en Parámetros y Opciones.

Todo termina en una columna después de la importación

Error de delimitador. El módulo escribe ; por defecto; tu consumidor esperaba , (o viceversa).

Vuelve a ejecutar la conversión con el delimitador que quiere el consumidor:

Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -Delimiter ","

…o indica al importador qué delimitador usa el archivo — en Excel vía Datos → Desde texto/CSV, en PowerShell vía Import-Csv -Delimiter ';'.

“Acceso denegado”

  • El directorio del registro DNS normalmente requiere derechos administrativos. Inicia PowerShell elevado, o ejecuta la tarea programada con una cuenta que tenga acceso.
  • Verifica también el acceso de escritura al directorio de salida, no solo el acceso de lectura al registro.
  • Para rutas SMB/UNC: una tarea que corre como SYSTEM se autentica en la red como la cuenta del equipo. Otorga permisos de compartición y NTFS a esa cuenta de equipo (o al grupo Domain Controllers), o usa una cuenta de servicio dedicada.
  • Si -RemoveSourceFile falla al final de una ejecución exitosa, la cuenta puede leer el registro pero no eliminarlo.

El procesamiento es muy lento

  1. Primero el disco — la conversión depende de I/O. Un volumen ocupado o una ruta de red lenta dominan el tiempo de ejecución.
  2. Usa -NoDetailsParsing si no necesitas el JSON con detalles del paquete; en registros con muchos detalles esto ahorra entre 30 y 50 %.
  3. Usa -ContextFilter Packet para escribir menos.
  4. Divide registros enormes con la rotación de registros del servidor DNS en lugar de convertir un archivo enorme.
  5. Considera una exclusión antivirus para el directorio del registro.

Más en Rendimiento.

La salida comprimida es más grande de lo esperado

Los registros con contenido muy diverso — muchos dominios únicos, muchos clientes distintos — se comprimen menos que los repetitivos. Eso es normal. ZIP aún suele lograr una reducción sustancial; si no es así, verifica si la columna Details está inflando el archivo y si realmente la necesitas.

Las estadísticas no coinciden con lo esperado

  • Confirma que usaste -OutputType Both o -OutputType Statistic. Con -OutputType CSV, no se generan archivos de estadísticas.
  • Count es un total, no un conteo distinto. Un cliente que pide el mismo nombre 500 veces aporta 500. Esta es la causa más frecuente de “ese número no puede ser correcto”.
  • Las estadísticas se agrupan por día. Un registro que abarca dos días produce filas para ambos.
  • Si ComputerName está vacío en los archivos de estadísticas, no se estableció -ComputerName durante la conversión.

La tarea programada funciona de forma interactiva pero no como tarea

Casi siempre es una de tres cosas:

  • Módulo no encontrado. SYSTEM con -NoProfile solo ve rutas de módulos a nivel máquina. Instala el módulo a nivel máquina o añade un Import-Module DNSServer.DebugLogParser explícito en la acción de la tarea.
  • Cultura incorrecta. La configuración regional de la cuenta de la tarea difiere de la tuya. Establece -InputCulture y -OutputCulture explícitamente.
  • Política de ejecución o script no firmado. Ajusta el -ExecutionPolicy de la tarea para que coincida con tu política de firma, y desbloquea archivos copiados de otro lugar.

Ejecuta manualmente la línea de comando exacta de la tarea en el mismo contexto (por ejemplo con PsExec como SYSTEM) para reproducir el problema.

Reportar un problema

Si nada de esto ayuda:

  1. Actualiza a la última versión del módulo y vuelve a intentarlo.

  2. Busca en los issues de GitHub el mismo síntoma.

  3. Recopila los diagnósticos:

    $PSVersionTable
    Get-Module DNSServer.DebugLogParser -ListAvailable | Select-Object Name, Version, Path
    Get-Culture
    

    además del comando exacto que ejecutaste, el mensaje de error completo incluyendo el seguimiento de pila, y — si puedes compartirlo — un pequeño extracto anonimizado del registro que reproduzca el problema.

  4. Abre un nuevo issue con esa información.

8 - Referencia de comandos del módulo

Aquí puedes encontrar una referencia para todos los comandos del módulo. Esta referencia está diseñada para ayudarte a encontrar rápidamente el comando que necesitas y entender cómo usarlo de manera efectiva.

Al hacer clic en un comando, serás llevado a una página detallada que proporciona información completa sobre el comando, incluyendo su sintaxis, parámetros, ejemplos y cualquier nota o consejo adicional para su uso.

8.1 - Convert-DNSDebugLogFile

SINOPSIS

Transforma los registros de depuración del servidor DNS de Windows en un formato CSV estructurado para análisis e informes.

SINTAXIS

__AllParameterSets

Convert-DNSDebugLogFile [-InputFile] <string[]> [[-OutputFile] <string>] [[-Delimiter] <string>]
 [[-ComputerName] <string>] [[-OutputType] <string>] [[-ContextFilter] <string[]>]
 [[-InputCulture] <cultureinfo>] [[-OutputCulture] <cultureinfo>] [-SkipHeaderValidation]
 [-RemoveSourceFile] [-CompressOutput] [-NoDetailsParsing] [-WhatIf] [-Confirm]

ALIAS

Este cmdlet tiene los siguientes alias,

DESCRIPCIÓN

Convierte archivos de registro de depuración del servidor DNS de Windows en datos CSV estructurados que pueden analizarse en Excel, Power BI, bases de datos SQL o herramientas SIEM.
Diseñado para análisis de seguridad, monitoreo de rendimiento, solución de problemas e informes de cumplimiento.

El cmdlet analiza los registros de depuración DNS y escribe una salida CSV consistente para análisis.
La salida CSV contiene 18 columnas, incluyendo una columna Information para texto de eventos/diagnósticos, una columna JSON opcional Details para bloques de detalles de paquetes, y una columna ComputerName siempre presente (vacía a menos que se especifique).

CARACTERÍSTICAS CLAVE:

  • Procesamiento en streaming que evita cargar el archivo completo en memoria (adecuado para registros muy grandes)
  • Análisis de alto rendimiento optimizado para archivos grandes (más de 100MB)
  • Delimitador CSV personalizable (por defecto: punto y coma)
  • Resúmenes estadísticos opcionales con métricas agregadas
  • Filtrado por contexto (Packet, Event, Note y contextos adicionales) para enfocarse en tipos específicos de entradas de registro
  • Análisis y formato de fechas conscientes de la cultura para servidores internacionales
  • Soporte de pipeline para procesamiento por lotes de múltiples archivos
  • Compresión opcional de archivos de salida (formato ZIP)
  • Eliminación automática opcional de archivos fuente tras el procesamiento
  • Validación de encabezados para asegurar la integridad de los datos

FORMATO DE SALIDA:
La columna ComputerName siempre se incluye al final de cada registro.
Si no se especifica el parámetro -ComputerName, la columna estará vacía.
Esto asegura una estructura de salida consistente para escenarios de consolidación multi-servidor.

RENDIMIENTO:
Optimizado usando StreamReader/StreamWriter con buffers de 64KB, procesamiento en streaming para manejo eficiente en memoria de archivos grandes, operaciones con cadenas en lugar de expresiones regulares, generación manual de CSV y recolección eficiente de estadísticas basada en tablas hash.

COMPATIBILIDAD:

  • PowerShell 5.1+ (ediciones Desktop y Core)
  • Windows Server 2016+
  • Formatos de registro DNS Server desde 2012 R2 hasta 2025

EJEMPLOS

EJEMPLO 1

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log"

Convierte el registro de depuración DNS usando la configuración predeterminada (archivos de datos y estadísticas con delimitador punto y coma).
Salida:

  • C:\Logs\dns.csv
  • C:\Logs\dns_Statistic.csv
  • C:\Logs\dns_PacketStatistic.csv

EJEMPLO 2

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputType CSV

Genera solo el archivo de datos sin estadísticas.
Salida: C:\Logs\dns.csv

EJEMPLO 3

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputType Statistic

Genera solo el archivo de estadísticas con métricas agregadas.
Salida:

  • C:\Logs\dns_Statistic.csv
  • C:\Logs\dns_PacketStatistic.csv

EJEMPLO 4

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -OutputFile "C:\Output\parsed.csv"

Convierte el registro a una ubicación de salida personalizada.
Salida: C:\Output\parsed.csv

EJEMPLO 5

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -Delimiter "," -ComputerName "DNS01" -OutputType Both

Convierte con delimitador coma y añade la columna ComputerName con valor “DNS01”.
Salida:

  • C:\Logs\dns.csv
  • C:\Logs\dns_Statistic.csv
  • C:\Logs\dns_PacketStatistic.csv

EJEMPLO 6

PS C:\> Get-ChildItem "C:\Logs\*.log" | Convert-DNSDebugLogFile -OutputType Both

Procesa por lotes múltiples archivos de registro de depuración DNS vía pipeline.
Salida: Para cada archivo .log, genera archivos .csv y _statistic.csv

EJEMPLO 7

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -CompressOutput

Convierte y comprime la salida en un archivo ZIP.
Salida: C:\Logs\dns.zip (contiene dns.csv + archivos de estadísticas)

EJEMPLO 8

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -RemoveSourceFile -Verbose

Convierte el registro y elimina el archivo fuente tras un procesamiento exitoso.
La salida detallada confirma la eliminación del archivo.

EJEMPLO 9

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -InputCulture 'de-DE' -OutputCulture 'en-US'

Analiza el formato de fecha alemán (DD.MM.AAAA) y lo convierte al formato estadounidense (MM/DD/AAAA).
Útil al procesar registros de servidores con configuraciones regionales diferentes.

EJEMPLO 10

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -ContextFilter 'Packet'

Convierte solo las entradas de paquetes de consulta/respuesta DNS, excluyendo entradas EVENT y Note.
Útil para enfocar el análisis en el tráfico DNS real.

EJEMPLO 11

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\dns.log" -ContextFilter 'Packet','Event'

Convierte tanto paquetes de consulta/respuesta DNS como eventos del servidor, excluyendo Note y otras entradas.
Útil para analizar el tráfico DNS junto con el contexto de eventos del servidor.

EJEMPLO 12

PS C:\> Get-ChildItem "C:\Logs\*.log" | Convert-DNSDebugLogFile -RemoveSourceFile -CompressOutput

Archivado automático de registros: procesa todos los registros, comprime la salida y elimina los archivos fuente.
Ideal para pipelines programados de procesamiento de registros.

EJEMPLO 13

PS C:\> Convert-DNSDebugLogFile -InputFile "C:\Logs\large-dns.log" -NoDetailsParsing

Procesa un archivo de registro grande con el análisis de detalles deshabilitado para máximo rendimiento.
Los bloques de detalle PACKET se omiten, dejando la columna Details vacía.
Útil al procesar archivos muy grandes cuando no se necesita el análisis detallado de la estructura de paquetes.

PARÁMETROS

-CompressOutput

Comprime los archivos CSV de salida en un archivo ZIP tras su creación.

Crea un archivo .zip que contiene los archivos CSV generados y luego elimina los CSV sin comprimir.
El archivo ZIP se crea en el mismo directorio que el CSV de salida con el mismo nombre base.

Beneficios:

  • Reduce significativamente el espacio en disco (los archivos CSV suelen comprimirse más del 90%)
  • Simplifica la gestión y archivo de archivos
  • Adecuado para almacenamiento a largo plazo

Ejemplo: El archivo de entrada ‘dns.log’ genera ‘dns.csv’ que se comprime a ‘dns.zip’, luego se elimina ‘dns.csv’.

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-ComputerName

Especifica el valor para la columna ComputerName en la salida CSV.
La columna ComputerName está siempre presente en la salida; si no se especifica este parámetro, la columna estará vacía.

Úsalo cuando consolides registros de múltiples servidores DNS para identificar el servidor origen en conjuntos de datos combinados.

Nota: Este NO es un parámetro de remoting.
Solo etiqueta la salida.
Si apuntas -InputFile a una ruta UNC, el archivo se lee desde esa ruta (no se realiza ejecución remota ni WinRM).

Type: String
DefaultValue: ''
SupportsWildcards: false
Aliases:
- Server
- DNSServer
- HostName
ParameterSets:
- Name: (All)
  Position: 3
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-Confirm

Solicita confirmación antes de ejecutar el cmdlet.

Cuando se especifica, pide confirmación antes de:

  • Procesar cada archivo de registro de depuración DNS
  • Eliminar archivos fuente (cuando se usa -RemoveSourceFile)
  • Sobrescribir archivos de salida existentes

Útil para procesamiento interactivo cuando quieres controlar qué archivos se procesan.

Type: SwitchParameter
DefaultValue: ''
SupportsWildcards: false
Aliases:
- cf
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-ContextFilter

Filtra qué tipos de entradas de registro incluir en la salida.
Acepta uno o varios valores.

Los registros de depuración DNS contienen diferentes tipos de contexto:

  • PACKET: Información de paquetes de consulta y respuesta DNS (datos principales)
  • EVENT: Eventos del servidor DNS (por ejemplo, “El servidor DNS ha iniciado.”)
  • Note: Notas y advertencias diagnósticas (por ejemplo, errores de socket, estados internos)
  • DSPoll, Init, Lookup, Recurse, Remote, Tombstone: Tipos de contexto adicionales

Valores válidos:

  • ‘All’: Incluye todos los tipos de contexto (predeterminado)
  • ‘Packet’: Incluye solo entradas PACKET (consultas/respuestas DNS)
  • ‘Event’: Incluye solo entradas EVENT (eventos del servidor)
  • ‘Note’: Incluye solo entradas Note (información diagnóstica)
  • Cualquier combinación: especifica múltiples valores para incluir tipos específicos de contexto

Predeterminado: All

Ejemplos:

  • ‘Packet’ filtra solo tráfico DNS
  • ‘Packet’,‘Event’ incluye tráfico DNS y eventos del servidor
  • ‘Note’,‘Event’ incluye notas diagnósticas y eventos del servidor

Nota: Al filtrar por ‘Event’ o ‘Note’, solo las columnas DateTime, ThreadId, Context e Information contendrán datos.
Las demás columnas (Protocol, ClientIP, etc.) estarán vacías.

Type: String[]
DefaultValue: "@('All')"
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 5
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-Delimiter

Especifica el carácter delimitador para la salida CSV.

Predeterminado: Punto y coma (;)

Alternativas comunes: Coma (,), Tabulación (`t), Barra vertical (|)

Usa punto y coma en regiones donde la coma es el separador decimal (Europa).
Usa coma para herramientas CSV estándar y bases de datos que esperan valores separados por coma.

Type: String
DefaultValue: ;
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 2
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-InputCulture

Especifica la cultura/locale para analizar valores de fecha/hora en el registro de depuración DNS.

Los registros de depuración del servidor DNS usan el formato de fecha de la configuración regional de Windows en el servidor donde se generó el registro.
Usa este parámetro cuando proceses registros de servidores con configuraciones regionales diferentes.

Predeterminado: Cultura actual

Ejemplos comunes:

  • ‘de-DE’ o ‘de-AT’: Formato alemán (DD.MM.AAAA o DD/MM/AAAA)
  • ’en-US’: Formato estadounidense (MM/DD/AAAA con AM/PM)
  • ’en-GB’: Formato británico (DD/MM/AAAA con hora 24h)
  • ‘sv-SE’: Formato sueco/ISO (AAAA-MM-DD)
Type: CultureInfo
DefaultValue: '[System.Globalization.CultureInfo]::CurrentCulture'
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 6
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-InputFile

Especifica la ruta del archivo de registro de depuración DNS a analizar.
Soporta arrays para procesar múltiples archivos.

Acepta entrada por pipeline desde Get-ChildItem u otros cmdlets que produzcan archivos.

Type: String[]
DefaultValue: ''
SupportsWildcards: false
Aliases:
- FullName
- FilePath
- InputPath
- File
- Path
ParameterSets:
- Name: (All)
  Position: 0
  IsRequired: true
  ValueFromPipeline: true
  ValueFromPipelineByPropertyName: true
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-NoDetailsParsing

Omite el análisis de los bloques de detalle PACKET en formato JSON estructurado.

Cuando se especifica, los registros PACKET con bloques de detalle tendrán la línea de información TCP/UDP en la columna Information, pero la columna Details permanecerá vacía.
Esto mejora significativamente el rendimiento del procesamiento para archivos grandes cuando no se necesita el análisis detallado de la estructura del paquete.

Usa este interruptor cuando:

  • Proceses archivos de registro muy grandes (más de 100MB) y solo necesites información básica de consultas
  • No requieras la estructura detallada (banderas de mensaje, secciones DNS) para el análisis
  • Priorices la velocidad de análisis sobre la completitud de datos

Impacto en rendimiento: Puede mejorar la velocidad de procesamiento entre un 30-50% para registros con muchos bloques de detalle PACKET.

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-OutputCulture

Especifica la cultura/locale para formatear valores de fecha/hora en los archivos CSV de salida.

Controla cómo se escriben los valores DateTime en el CSV.
Úsalo cuando los archivos CSV serán consumidos por aplicaciones o sistemas con configuraciones regionales específicas.

Predeterminado: Cultura actual

Ejemplos comunes:

  • ’en-US’: Formato estadounidense (MM/DD/AAAA)
  • ‘de-DE’: Formato alemán (DD.MM.AAAA)
  • ‘sv-SE’ o InvariantCulture: Formato ISO (AAAA-MM-DD) para máxima compatibilidad
Type: CultureInfo
DefaultValue: '[System.Globalization.CultureInfo]::CurrentCulture'
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 7
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-OutputFile

Especifica la ruta para el archivo CSV de salida.
Si no se especifica, usa el nombre del archivo de entrada con extensión .csv en el mismo directorio que el archivo de entrada.

Importante: Debe ser una ruta de archivo, no un directorio.
Si quieres usar el directorio del archivo de entrada con un nombre personalizado, especifica la ruta completa incluyendo el nombre del archivo.

Type: String
DefaultValue: ''
SupportsWildcards: false
Aliases:
- Output
- Destination
- OutFile
- OutputPath
ParameterSets:
- Name: (All)
  Position: 1
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-OutputType

Especifica el tipo de salida a generar.

Valores válidos:

  • ‘CSV’: Genera solo el archivo de datos con todas las entradas analizadas
  • ‘Statistic’: Genera solo los archivos de estadísticas con métricas agregadas
  • ‘Both’: Genera ambos archivos, datos y estadísticas (predeterminado)

Predeterminado: Both

Cuando se generan estadísticas, se crean dos archivos separados:

  • ‘_Statistic.csv’: Conteos resumidos por tipo de contexto y día (Date, Context, Count, ComputerName)
  • ‘_PacketStatistic.csv’: Conteos detallados PACKET por día según IP cliente, protocolo, dirección y tipo de consulta (Date, ClientIP, Protocol, Direction, QuestionType, Count, ComputerName)
Type: String
DefaultValue: Both
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: 4
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-RemoveSourceFile

Elimina el archivo fuente de registro de depuración DNS tras un procesamiento exitoso.

Úsalo para pipelines automatizados de procesamiento de registros o gestión de espacio en disco.
El archivo fuente solo se elimina si el procesamiento finaliza correctamente y se crean todos los archivos de salida.

Seguridad: No puede usarse junto con -SkipHeaderValidation para evitar eliminación accidental de archivos inválidos.

Advertencia: Los archivos fuente se eliminan permanentemente.
Asegúrate de que los archivos de salida sean válidos antes de usar esta opción.

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-SkipHeaderValidation

Omite la validación del encabezado del registro de depuración DNS.

Por defecto, el cmdlet valida que los archivos de entrada tengan un encabezado válido de registro de depuración del servidor DNS.
Usa este interruptor para procesar archivos sin validación, lo que puede ser útil para:

  • Formatos de registro modificados o personalizados
  • Solución de problemas de validación
  • Registros no estándar o preprocesados

Advertencia: Puede resultar en errores de procesamiento si el archivo no es un registro DNS válido.

Type: SwitchParameter
DefaultValue: False
SupportsWildcards: false
Aliases: []
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

-WhatIf

Muestra qué ocurriría si se ejecuta el cmdlet.
El cmdlet no se ejecuta.

Cuando se especifica, muestra información detallada sobre las operaciones que se realizarían sin ejecutarlas realmente.
Útil para:

  • Previsualizar qué archivos se procesarían
  • Verificar rutas de archivos de salida antes del procesamiento
  • Probar scripts antes de ejecutarlos en producción
Type: SwitchParameter
DefaultValue: ''
SupportsWildcards: false
Aliases:
- wi
ParameterSets:
- Name: (All)
  Position: Named
  IsRequired: false
  ValueFromPipeline: false
  ValueFromPipelineByPropertyName: false
  ValueFromRemainingArguments: false
DontShow: false
AcceptedValues: []
HelpMessage: ''

CommonParameters

Este cmdlet soporta los parámetros comunes: -Debug, -ErrorAction, -ErrorVariable,
-InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable,
-ProgressAction, -Verbose, -WarningAction y -WarningVariable. Para más información, consulta
about_CommonParameters.

ENTRADAS

System.String[]

NOTAS

Versión : 1.7.2.1
Autor : Andi Bellstedt, Copilot, Patrick Charbonnier (Silent Waters IT Consulting S.L.)
Fecha : 2026-07-24
Palabras clave : Microsoft Windows Server, DNSServer, DNS, DebugLog, LogParser

ENLACES RELACIONADOS

9 - Ejemplos de Uso

Aquí puedes encontrar ejemplos prácticos de cómo usar el módulo en escenarios reales. Estos ejemplos están diseñados para ayudarte a entender cómo aplicar la funcionalidad del módulo.

Estos son ejemplos con un poco más de profundidad y contexto. Si solo quieres ver el uso de los comandos del módulo, consulta la referencia de comandos.

9.1 - Flujo de trabajo de análisis de seguridad con SQL Server

Convierte registros de depuración DNS a CSV con DNSServer.DebugLogParser, importa el resultado en SQL Server y ejecuta una consulta simple para detectar actividad sospechosa de registros TXT.

Este ejemplo muestra un flujo de trabajo práctico para análisis de seguridad: analiza un registro de depuración DNS con Convert-DNSDebugLogFile, importa el CSV generado en SQL Server y ejecuta una consulta que resalta volúmenes inusualmente altos de búsquedas de registros TXT.

Para una mejor interoperabilidad, este ejemplo escribe marcas de tiempo en un formato tipo ISO usando -OutputCulture 'sv-SE'.

Módulos requeridos

Este ejemplo utiliza los siguientes módulos de PowerShell:

  • DNSServer.DebugLogParser
  • SqlServer

Instálalos si es necesario:

Install-Module -Name DNSServer.DebugLogParser -Scope CurrentUser
Install-Module -Name SqlServer -Scope CurrentUser

Escenario

Usa este flujo de trabajo cuando quieras mover datos analizados de registros de depuración DNS a SQL Server para poder:

  • buscar grandes conjuntos de datos de forma eficiente
  • crear consultas de detección repetibles
  • correlacionar actividad en múltiples servidores DNS
  • conservar datos normalizados para investigaciones posteriores

Salida del paso de conversión

Convert-DNSDebugLogFile no escribe directamente en SQL Server. Primero crea un archivo CSV. Ese archivo CSV es el conjunto de datos que se importa a la base de datos.

En este ejemplo:

  • registro de entrada: C:\Administration\Logs\DNS\dns.log
  • CSV generado: C:\Administration\Logs\DNS\dns.csv
  • tabla destino: dbo.DNSQueries

Crear la tabla destino

Ejecuta la siguiente instrucción una vez en SQL Server para crear la tabla destino.

IF OBJECT_ID('dbo.DNSQueries', 'U') IS NULL
BEGIN
    CREATE TABLE dbo.DNSQueries (
        DateTime      datetime2(0)   NOT NULL,
        ThreadId      int            NULL,
        Context       nvarchar(20)   NULL,
        PacketId      int            NULL,
        Protocol      nvarchar(10)   NULL,
        Direction     nvarchar(10)   NULL,
        ClientIP      nvarchar(64)   NULL,
        Xid           nvarchar(16)   NULL,
        Type          nvarchar(16)   NULL,
        Opcode        nvarchar(16)   NULL,
        FlagsHex      nvarchar(16)   NULL,
        FlagsChar     nvarchar(16)   NULL,
        ResponseCode  nvarchar(32)   NULL,
        QuestionType  nvarchar(32)   NULL,
        QuestionName  nvarchar(512)  NULL,
        Information   nvarchar(max)  NULL,
        Details       nvarchar(max)  NULL,
        ComputerName  nvarchar(256)  NULL
    );
END;

Convertir el registro e importar el CSV

El siguiente ejemplo en PowerShell realiza el flujo completo:

  1. importa los módulos requeridos
  2. convierte el registro de depuración DNS a CSV
  3. carga el CSV generado
  4. importa masivamente las filas a SQL Server
# Requires -Modules DNSServer.DebugLogParser, SqlServer

Import-Module -Name DNSServer.DebugLogParser -ErrorAction Stop
Import-Module -Name SqlServer -ErrorAction Stop

$logPath = 'C:\Administration\Logs\DNS\dns.log'
$csvPath = 'C:\Administration\Logs\DNS\dns.csv'
$serverInstance = 'SQLServer'
$databaseName = 'DNSLogs'
$delimiter = ';'

$createTableSql = @'
IF OBJECT_ID('dbo.DNSQueries', 'U') IS NULL
BEGIN
    CREATE TABLE dbo.DNSQueries (
        DateTime      datetime2(0)   NOT NULL,
        ThreadId      int            NULL,
        Context       nvarchar(20)   NULL,
        PacketId      int            NULL,
        Protocol      nvarchar(10)   NULL,
        Direction     nvarchar(10)   NULL,
        ClientIP      nvarchar(64)   NULL,
        Xid           nvarchar(16)   NULL,
        Type          nvarchar(16)   NULL,
        Opcode        nvarchar(16)   NULL,
        FlagsHex      nvarchar(16)   NULL,
        FlagsChar     nvarchar(16)   NULL,
        ResponseCode  nvarchar(32)   NULL,
        QuestionType  nvarchar(32)   NULL,
        QuestionName  nvarchar(512)  NULL,
        Information   nvarchar(max)  NULL,
        Details       nvarchar(max)  NULL,
        ComputerName  nvarchar(256)  NULL
    );
END
'@

Convert-DNSDebugLogFile `
    -InputFile $logPath `
    -ComputerName 'DNS01' `
    -OutputType CSV `
    -OutputFile $csvPath `
    -Delimiter $delimiter `
    -OutputCulture 'sv-SE'

$rows = Import-Csv -Path $csvPath -Delimiter $delimiter

if (-not $rows) {
    throw "El archivo CSV generado '$csvPath' no contiene filas."
}

$dataTable = [System.Data.DataTable]::new()
foreach ($columnName in $rows[0].PSObject.Properties.Name) {
    $null = $dataTable.Columns.Add($columnName, [string])
}

foreach ($row in $rows) {
    $dataRow = $dataTable.NewRow()
    foreach ($column in $dataTable.Columns) {
        $columnName = $column.ColumnName
        $dataRow[$columnName] = $row.$columnName
    }

    $null = $dataTable.Rows.Add($dataRow)
}

$connectionString = "Server=$serverInstance;Database=$databaseName;Integrated Security=True"
$connection = [System.Data.SqlClient.SqlConnection]::new($connectionString)

try {
    $connection.Open()

    $command = $connection.CreateCommand()
    $command.CommandText = $createTableSql
    $null = $command.ExecuteNonQuery()

    $bulkCopy = [System.Data.SqlClient.SqlBulkCopy]::new($connection)
    $bulkCopy.DestinationTableName = 'dbo.DNSQueries'

    foreach ($column in $dataTable.Columns) {
        $null = $bulkCopy.ColumnMappings.Add($column.ColumnName, $column.ColumnName)
    }

    $bulkCopy.WriteToServer($dataTable)
}
finally {
    $connection.Dispose()
}

Consulta para actividad sospechosa en registros TXT

Una vez que los datos están en SQL Server, puedes buscar clientes que realicen un número inusualmente alto de consultas de registros TXT.

SELECT
    ComputerName,
    ClientIP,
    QuestionName,
    COUNT(*) AS QueryCount
FROM dbo.DNSQueries
WHERE QuestionType = 'TXT'
GROUP BY
    ComputerName,
    ClientIP,
    QuestionName
HAVING COUNT(*) > 100
ORDER BY QueryCount DESC;

Si prefieres ejecutar la consulta desde PowerShell, usa Invoke-Sqlcmd del módulo SqlServer:

$query = @'
SELECT
    ComputerName,
    ClientIP,
    QuestionName,
    COUNT(*) AS QueryCount
FROM dbo.DNSQueries
WHERE QuestionType = 'TXT'
GROUP BY
    ComputerName,
    ClientIP,
    QuestionName
HAVING COUNT(*) > 100
ORDER BY QueryCount DESC;
'@

Invoke-Sqlcmd `
    -ServerInstance 'SQLServer' `
    -Database 'DNSLogs' `
    -Query $query

Por qué las consultas TXT son interesantes

Los volúmenes altos de búsquedas de registros TXT pueden valer la pena revisarse porque pueden indicar:

  • túneles DNS
  • exfiltración de datos por DNS
  • abuso de registros TXT por malware o herramientas
  • clientes inusualmente ruidosos o mal configurados

Esta consulta es solo un punto de partida. En producción, deberías ajustar el umbral y agregar filtros que se adapten a tu entorno.

Notas operativas

  • Import-Csv lee el archivo completo en memoria. Para exportaciones de registros muy grandes, considera un enfoque de streaming en lugar de construir un DataTable completo.
  • Mantén -ComputerName en el paso de conversión para que los registros sigan siendo atribuibles después de la ingestión centralizada.
  • Usa un delimitador y cultura consistentes durante la exportación e importación.
  • Valida la retención, indexación y control de acceso en SQL Server antes de usar este flujo para almacenamiento a largo plazo.

9.2 - Uso práctico en un entorno de dominio (colección y conversión impulsadas por GPO)

Este ejemplo demuestra cómo implementar un flujo de trabajo impulsado por GPO para recopilar y convertir registros de depuración DNS en controladores de dominio.

Este documento describe un ejemplo práctico y completo de ejecución de DNSServer.DebugLogParser en un entorno de dominio de Active Directory, centrado en la conversión de registros de depuración del servidor DNS de Windows en controladores de dominio.

Este ejemplo se acompaña de un archivo ZIP, que proporciona los artefactos de la política usados para implementar el flujo de trabajo descrito aquí.
Los artefactos más relevantes son el manifest.xml de respaldo, el informe GPO, Files.xml, Set-DNSServerDebugLogging.ps1 y ScheduledTasks.xml.

Escenario

  • Varios controladores de dominio (DC) alojan el rol de servidor DNS.
  • El registro de depuración DNS está habilitado y configurado de forma coherente en cada DC mediante una tarea programada (escribiendo archivos de registro en C:\Administration\Logs\DNSServer).
  • Un proceso gestionado centralmente convierte los registros a CSV para:
    • análisis de seguridad
    • informes operativos
    • resolución de problemas
    • cumplimiento/retención

Resultados esperados

  • Configuraciones de conversión coherentes en todos los DC
  • Ubicación y nombres de salida predecibles
  • Compresión opcional para reducir el espacio de almacenamiento
  • Salidas estadísticas opcionales para resúmenes diarios rápidos
  • Riesgo mínimo en el host, con consideraciones explícitas de reejecución y limpieza

Arquitectura sugerida

Modelo de recopilación: conversión local + extracción central

  1. Cada DC escribe los registros de depuración DNS en disco con activación de rollover.
  2. Cada DC convierte los archivos *.log rotados en un CSV de datos y CSVs de estadísticas, luego comprime las salidas en *.zip según un horario (Programador de tareas).
  3. Las salidas se escriben junto a los archivos de registro para mantener la canalización simple.
  4. Un servidor central recopila las salidas *.zip, por ejemplo mediante ingestión por recurso compartido de archivos, copia programada, reenviador SIEM o un colector basado en agente.

Este modelo minimiza las lecturas de red de archivos de registro sin procesar grandes y mantiene el análisis cerca de los datos.

Flujo de trabajo GPO

El flujo de trabajo se implementa mediante la Directiva de Grupo (configuración de equipo) para asegurar configuraciones coherentes en todos los controladores de dominio.

Implementación de referencia incluida en este repositorio (informe GPO):

  • Nombre del archivo/informe: T0-C-Analytics-DNSDebugLogging
  • ID de respaldo: {2B6F16BC-0E7C-4787-83D7-2854FED882EE}
  • Destino del enlace GPO: corp.company.com/Domain Controllers
  • Filtro de elementos (usado tanto para despliegue de archivos como para tareas programadas): solo se aplica si existe C:\Windows\System32\dns.exe

1) Requisitos previos (carpetas + módulo)

El respaldo proporcionado asume que estas carpetas ya existen. Añade elementos GPP separados si quieres que el despliegue las cree automáticamente:

  • C:\Administration\Scripts
  • C:\Administration\Logs\DNSServer

El respaldo también asume que Convert-DNSDebugLogFile ya está disponible en los DC. La tarea de conversión inicia Windows PowerShell 5.1 con -NoProfile y no importa el módulo explícitamente, por lo que el módulo debe estar instalado en una ruta de módulo de Windows PowerShell a nivel máquina visible para LocalSystem. Enfoques recomendados:

  • Instalar DNSServer.DebugLogParser en los DC, por ejemplo desde PowerShell Gallery (si la política lo permite).
  • Desplegar el módulo vía repositorio interno / recurso compartido de archivos para que sea detectable en $env:PSModulePath
  • Añadir un Import-Module explícito a la acción de la tarea si quieres un comportamiento de carga determinista

2) Desplegar el script de configuración de registro de depuración (GPP Archivos)

La GPO despliega el script:

  • Origen (en SYSVOL vía GPP): %GptPath%\Preferences\Files\Set-DNSServerDebugLogging.ps1
  • Destino (en cada DC): C:\Administration\Scripts\Set-DNSServerDebugLogging.ps1

Esto se implementa en el elemento de preferencia GPP Archivos en Files.xml.

3) Tarea programada: configurar el registro de depuración DNS

La GPO crea una tarea programada llamada Set-DNSServerDebugLogging.

  • Contexto de seguridad en el respaldo suministrado: SYSTEM con tipo de inicio de sesión S4U
  • Disparador en el respaldo suministrado: diario (inicio 2025-03-01T00:00:01)
  • Acción en ScheduledTasks.xml:
    • powershell.exe -ExecutionPolicy RemoteSigned -command " & { C:\Administration\Scripts\Set-DNSServerDebugLogging.ps1 }"
    • Directorio de trabajo: C:\Administration\Scripts

El script vinculado Set-DNSServerDebugLogging.ps1 configura el registro de depuración DNS mediante Get-DnsServerDiagnostics / Set-DnsServerDiagnostics y (notablemente):

  • Habilita el registro en archivo + rollover
  • Escribe en: C:\Administration\Logs\DNSServer\DnsDebugLog_<COMPUTERNAME>.<Domain>_.log
  • Usa un tamaño de rollover de 10 MB por archivo
  • Captura principalmente actividad relacionada con consultas (consultas + notificaciones + actualizaciones + transacciones de preguntas) y excluye el registro completo de paquetes

4) Tarea programada: convertir registros de depuración rotados a CSV comprimido

La GPO crea una tarea programada llamada Convert-DNSDebugLogs.

  • Contexto de seguridad en el respaldo suministrado: SYSTEM con tipo de inicio de sesión InteractiveToken
  • Disparador en el respaldo suministrado: diario (inicio 2026-01-01T00:30:00)
  • Directorio de trabajo: C:\Administration\Logs\DNSServer
  • Acción en ScheduledTasks.xml (formateado para legibilidad):
Get-ChildItem .\*.log |
  Sort-Object lastwritetime, Name -Descending |
  Select-Object -Skip 1 |
  Convert-DNSDebugLogFile `
    -ComputerName $env:COMPUTERNAME `
    -Delimiter ';' `
    -OutputType Both `
    -ContextFilter Packet `
    -OutputCulture sv-SE `
    -CompressOutput

Notas de diseño:

  • Select-Object -Skip 1 evita intencionadamente procesar el archivo de registro más nuevo (activo). Convert-DNSDebugLogFile puede leer un registro que el servidor DNS tiene abierto actualmente, pero ese archivo cambia mientras se lee: la salida puede perder las entradas más nuevas o terminar con un registro truncado, y dos ejecuciones no producen resultados idénticos. Omitir el archivo activo mantiene la salida programada reproducible.
  • Eso significa que los datos actuales solo se exportan después del rollover; en DCs de bajo volumen, el registro activo puede permanecer sin procesar por más de un día. Reduce el tamaño de rollover si ese retraso es demasiado largo para tu caso de uso.
  • Como Convert-DNSDebugLogFile por defecto usa -OutputFile en “misma carpeta, mismo nombre, .csv”, las salidas quedan junto a las entradas *.log.
  • Con -CompressOutput, cada registro procesado produce un *.zip y los CSV intermedios se eliminan.
  • A menos que archives o elimines los archivos *.log procesados, ejecuciones posteriores reprocesarán cada registro no activo.
  • La tarea lanza error si $Error.Count -gt 0 para señalar una ejecución fallida.

5) Ingesta central

Opciones (elige una):

  • Ingesta por recurso compartido de archivos: el DC escribe (o copia) C:\Administration\Logs\DNSServer\*.zip a \\fileserver\share\dns\$env:COMPUTERNAME\... (concede permisos de recurso compartido y NTFS a las cuentas de equipo DC o al grupo Domain Controllers si la tarea se ejecuta como SYSTEM)
  • Modelo pull: trabajo central lee \\dc\C$\Administration\Logs\DNSServer\*.zip (menos preferido; requiere recursos compartidos administrativos)
  • Reenviador agente: SIEM / canalización de registros que envía las salidas *.zip

Consideraciones operativas

  • Mínimo privilegio: las tareas se ejecutan como SYSTEM; asegúrate de que las carpetas locales sean escribibles y que cualquier destino UNC conceda acceso a la cuenta de equipo si se usa.
  • Política de firma: ambas tareas usan -ExecutionPolicy RemoteSigned; firma o desbloquea el script y módulo desplegados según tu política.
  • Uso de disco: -CompressOutput ayuda significativamente, pero este flujo no elimina los registros fuente; planifica retención y limpieza.
  • Comportamiento de reprocesamiento: a menos que archives o elimines los registros procesados, la tarea de conversión procesará cada archivo *.log no activo nuevamente en ejecuciones posteriores. Esto es simple y robusto, pero puede sobrescribir salidas y crear ingestiones duplicadas aguas abajo si tu colector no deduplica.
  • Consolidación multi-DC: -ComputerName $env:COMPUTERNAME se incluye para que los conjuntos de datos consolidados sigan siendo rastreables. Ten en cuenta que -ComputerName solo etiqueta la salida — no realiza conexión remota.
  • Recursos compartidos de red: Convert-DNSDebugLogFile puede leer registros fuente desde rutas SMB/UNC, pero convertir localmente y enviar los resultados comprimidos sigue siendo el mejor patrón para registros sin procesar grandes. Si usas una ruta UNC, recuerda que una tarea ejecutándose como SYSTEM se autentica en la red como la cuenta de equipo y necesita permisos de recurso compartido y NTFS allí.
  • Formato de fecha: -OutputCulture sv-SE se usa deliberadamente para que las marcas de tiempo se escriban como 2026-01-20 23:00:16. Ese formato es leído sin indicación por SQL Server, Power BI y la mayoría de herramientas de importación, independientemente de la configuración regional del DC que produjo el registro.
  • Validación: la validación del encabezado permanece habilitada porque la tarea no usa -SkipHeaderValidation (recomendado).

Validar y adaptar (usando el ZIP)

Usa el archivo ZIP como implementación de referencia, luego alinea los siguientes aspectos a tu entorno:

  • Alcance objetivo: qué DCs / UOs reciben la política
  • Identidad de ejecución: confirma que ambas tareas programadas usan el tipo de inicio de sesión previsto (S4U vs InteractiveToken) o normalízalos a tu estándar
  • Creación de carpetas: decide si C:\Administration\Scripts y C:\Administration\Logs\DNSServer se preconfiguran en otro lugar o deben crearse con elementos GPP adicionales
  • Rutas: confirma que C:\Administration\Scripts y C:\Administration\Logs\DNSServer cumplen con tus estándares
  • Retención: decide si conservar los registros sin procesar y por cuánto tiempo (especialmente si habilitas opciones de limpieza)
  • Ingesta: confirma dónde se escriben las salidas CSV/ZIP y cómo se recopilan centralmente

Si quieres validar la configuración exacta de la GPO sin importarla, las fuentes autorizadas en este repositorio son:

9.3 - Ejemplo de tarea programada

Este ejemplo muestra cómo crear una tarea programada de Windows que ejecuta un script de PowerShell para procesar los registros de depuración DNS diariamente.

Este script crea una tarea programada de Windows que se ejecuta diariamente a las 2:00 AM. Importa el módulo y procesa todos los archivos de registro en la carpeta donde se ejecuta el script (en este ejemplo “C:\Administration\Logs\DNS”). El proceso comprime la salida en archivos ZIP y elimina el original para mantener la limpieza.

$actionParams = @{
    Execute = "powershell.exe"
    Argument = '-ExecutionPolicy RemoteSigned -Command "Import-Module DNSServer.DebugLogParser; Get-ChildItem .\*.log | Sort-Object lastwritetime, Name -Descending | Convert-DNSDebugLogFile -ComputerName $env:COMPUTERNAME -Delimiter \";\" -OutputType Both -ContextFilter Packet -OutputCulture sv-SE -CompressOutput"'
    WorkingDirectory = "C:\Administration\Logs\DNS"
}
$Action = New-ScheduledTaskAction @actionParams

$Trigger = New-ScheduledTaskTrigger -Daily -At "2:00AM"

Register-ScheduledTask -TaskName "Process DNS Logs" -Action $Action -Trigger $Trigger -Description "Convert DNS debug logs to CSV daily"