Collect logs from Windows DHCP server
DHCP (Dynamic Host Configuration Protocol) is a network management protocol that dynamically assigns IP addresses to each client machine on your network. DHCP Server events are written to DHCP audit log files (if configured) and Windows Event Log.
NXLog Agent can be configured to collect both DHCP audit logs and DHCP server logs located in the Windows Event Log. With its native xm_csv, im_file, and im_msvistalog modules, NXLog Agent collects logs from these sources and normalizes them to a single format and schema that your SIEM can understand.
DHCP audit logging
The Windows DHCP Server provides an audit logging feature that writes server activity to log files. NXLog Agent can be configured to read and parse these logs.
The log files are named DhcpSrvLog-<DAY>.log
for IPv4 and DhcpV6SrvLog-<DAY>.log
for IPv6.
For example, Thursday’s log files are DhcpSrvLog-Thu.log
and DhcpV6SrvLog-Thu.log
.
ID,Date,Time,Description,IP Address,Host Name,MAC Address,User Name, TransactionID, QResult,Probationtime, CorrelationID,Dhcid,VendorClass(Hex),VendorClass(ASCII),UserClass(Hex),UserClass(ASCII),RelayAgentInformation,DnsRegError.
00,05/11/18,03:14:55,Started,,,,,0,6,,,,,,,,,0
55,05/11/18,03:14:55,Authorized(servicing),,test.com,,,0,6,,,,,,,,,0
ID,Date,Time,Description,IPv6 Address,Host Name,Error Code, Duid Length, Duid Bytes(Hex),User Name,Dhcid,Subnet Prefix.
11010,05/11/18,03:14:55,DHCPV6 Started,,,,,,,,,,
1103,05/11/18,03:14:55,Authorized(servicing),,test.com,,,,,,,,
The DHCP audit log can be configured with PowerShell or the DHCP Management MMC snap-in.
The default audit log path, C:\Windows\System32\dhcp , is architecture-specific.
To collect DHCP audit logs using the 32-bit NXLog Agent on a 64-bit Windows system, it is recommended to change the log path to another directory that is not redirected to SysWOW64 .
For this reason, the following instructions use C:\dhcp .
If NXLog Agent is running on the system’s native architecture, it is not necessary to change the log file location from the default.
|
Configure DHCP audit logs via PowerShell
-
To view the current DHCP audit log configuration, run the following command: (see Get-DhcpServerAuditLog on Microsoft Docs).
> Get-DhcpServerAuditLog Path : C:\Windows\system32\dhcp Enable : True MaxMBFileSize : 70 DiskCheckInterval : 50 MinMBDiskSpace : 20
-
To set the audit log configuration, run this command: (see Set-DhcpServerAuditLog on Microsoft Docs).
> Set-DhcpServerAuditLog -Enable $True -Path C:\dhcp
-
The DHCP server must be restarted for the configuration changes to take effect:
> Restart-Service DHCPServer
Configure DHCP audit logs via the DHCP Management Console
Follow these steps to configure DHCP audit logging. Any changes to the audit log settings apply to both IPv4 and IPv6 after the DHCP server is restarted.
-
Run the DHCP MMC snap-in (
dhcpmgmt.msc
), expand the server for which to configure logging, and click on IPv4. -
Right-click on IPv4 and click Properties. Note that the context menu is not fully populated until after the IPv4 menu has been expanded at least once.
-
Make sure Enable DHCP audit logging is checked.
-
Open the Advanced tab, change the Audit log file path, and click OK.
-
Restart the DHCP server by right-clicking the server and clicking All Tasks > Restart.
Collect DHCP server audit logs with NXLog Agent
The DHCP audit logs are stored in CSV format with a large free-form header containing a list of event ID descriptions and other details.
This configuration uses a batch/PowerShell polyglot script with the include_stdout directive to fetch the DHCP audit log location.
The im_file module reads the audit logs and the xm_csv module parses the lines into fields.
Any line that does not match the /^\d+,/
regular expression is discarded with the drop() procedure (all the header lines are dropped).
The event ID
and QResult
codes are resolved automatically, with corresponding $Message
and $QMessage
fields added where applicable.
If DHCP audit logging is disabled, the script will print an error, and NXLog Agent will abort during the configuration check. |
<Extension dhcp_csv_parser>
Module xm_csv
Fields ID, Date, Time, Description, IPAddress, Hostname, MACAddress, \
UserName, TransactionID, QResult, ProbationTime, CorrelationID, \
DHCID, VendorClassHex, VendorClassASCII, UserClassHex, \
UserClassASCII, RelayAgentInformation, DnsRegError
</Extension>
<Extension dhcpv6_csv_parser>
Module xm_csv
Fields ID, Date, Time, Description, IPv6Address, Hostname, ErrorCode, \
DuidLength, DuidBytesHex, UserName, Dhcid, SubnetPrefix
</Extension>
<Input dhcp_server_audit>
Module im_file
include_stdout %CONFDIR%\dhcp_server_audit_include.cmd
<Exec>
# Only process lines that begin with an event ID
if $raw_event =~ /^\d+,/
{
$FileName = file_name();
if $FileName =~ /DhcpSrvLog-/
{
dhcp_csv_parser->parse_csv();
$QResult = integer($QResult);
if $QResult == 0 $QMessage = "NoQuarantine";
else if $QResult == 1 $QMessage = "Quarantine";
else if $QResult == 2 $QMessage = "Drop Packet";
else if $QResult == 3 $QMessage = "Probation";
else if $QResult == 6 $QMessage = "No Quarantine Information";
}
else
{
dhcpv6_csv_parser->parse_csv();
}
$EventTime = strptime($Date + ' ' + $Time, '%m/%d/%y %H:%M:%S');
$ID = integer($ID);
# DHCP Event IDs
if $ID == 0 $Message = "The log was started.";
else if $ID == 1 $Message = "The log was stopped.";
else if $ID == 2
$Message = "The log was temporarily paused due to low disk space.";
else if $ID == 10 $Message = "A new IP address was leased to a client.";
else if $ID == 11 $Message = "A lease was renewed by a client.";
else if $ID == 12 $Message = "A lease was released by a client.";
else if $ID == 13
$Message = "An IP address was found to be in use on the network.";
else if $ID == 14
$Message = "A lease request could not be satisfied because the " +
"scope's address pool was exhausted.";
else if $ID == 15 $Message = "A lease was denied.";
else if $ID == 16 $Message = "A lease was deleted.";
else if $ID == 17
$Message = "A lease was expired and DNS records for an expired " +
"leases have not been deleted.";
else if $ID == 18
$Message = "A lease was expired and DNS records were deleted.";
else if $ID == 20
$Message = "A BOOTP address was leased to a client.";
else if $ID == 21
$Message = "A dynamic BOOTP address was leased to a client.";
else if $ID == 22
$Message = "A BOOTP request could not be satisfied because the " +
"scope's address pool for BOOTP was exhausted.";
else if $ID == 23
$Message = "A BOOTP IP address was deleted after checking to see " +
"it was not in use.";
else if $ID == 24
$Message = "IP address cleanup operation has began.";
else if $ID == 25
$Message = "IP address cleanup statistics.";
else if $ID == 30
$Message = "DNS update request to the named DNS server.";
else if $ID == 31 $Message = "DNS update failed.";
else if $ID == 32 $Message = "DNS update successful.";
else if $ID == 33
$Message = "Packet dropped due to NAP policy.";
else if $ID == 34
$Message = "DNS update request failed as the DNS update request " +
"queue limit exceeded.";
else if $ID == 35 $Message = "DNS update request failed.";
else if $ID == 36
$Message = "Packet dropped because the server is in failover " +
"standby role or the hash of the client ID does not " +
"match.";
else if ($ID >= 50 and $ID < 1000)
$Message = "Codes above 50 are used for Rogue Server Detection " +
"information.";
# DHCPv6 Event IDs
else if $ID == 11000 $Message = "DHCPv6 Solicit.";
else if $ID == 11001 $Message = "DHCPv6 Advertise.";
else if $ID == 11002 $Message = "DHCPv6 Request.";
else if $ID == 11003 $Message = "DHCPv6 Confirm.";
else if $ID == 11004 $Message = "DHCPv6 Renew.";
else if $ID == 11005 $Message = "DHCPv6 Rebind.";
else if $ID == 11006 $Message = "DHCPv6 Decline.";
else if $ID == 11007 $Message = "DHCPv6 Release.";
else if $ID == 11008 $Message = "DHCPv6 Information Request.";
else if $ID == 11009 $Message = "DHCPv6 Scope Full.";
else if $ID == 11010 $Message = "DHCPv6 Started.";
else if $ID == 11011 $Message = "DHCPv6 Stopped.";
else if $ID == 11012 $Message = "DHCPv6 Audit log paused.";
else if $ID == 11013 $Message = "DHCPv6 Log File.";
else if $ID == 11014 $Message = "DHCPv6 Bad Address.";
else if $ID == 11015 $Message = "DHCPv6 Address is already in use.";
else if $ID == 11016 $Message = "DHCPv6 Client deleted.";
else if $ID == 11017 $Message = "DHCPv6 DNS record not deleted.";
else if $ID == 11018 $Message = "DHCPv6 Expired.";
else if $ID == 11019
$Message = "DHCPv6 Leases Expired and Leases Deleted.";
else if $ID == 11020 $Message = "DHCPv6 Database cleanup begin.";
else if $ID == 11021 $Message = "DHCPv6 Database cleanup end.";
else if $ID == 11022 $Message = "DNS IPv6 Update Request.";
else if $ID == 11023 $Message = "DNS IPv6 Update Failed.";
else if $ID == 11024 $Message = "DNS IPv6 Update Successful.";
else if $ID == 11028
$Message = "DNS IPv6 update request failed as the DNS update " +
"request queue limit exceeded.";
else if $ID == 11029 $Message = "DNS IPv6 update request failed.";
else if $ID == 11030
$Message = "DHCPv6 stateless client records purged.";
else if $ID == 11031
$Message = "DHCPv6 stateless client record is purged as the " +
"purge interval has expired for this client record.";
else if $ID == 11032
$Message = "DHCPV6 Information Request from IPV6 Stateless Client.";
else $Message = "No message specified for this Event ID.";
}
# Discard header lines (which do not begin with an event ID)
else drop();
</Exec>
</Input>
@( Set "_= (
REM " ) <#
)
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
powershell.exe -ExecutionPolicy Bypass -NoProfile ^
-Command "iex ((gc '%~f0') -join [char]10)"
EndLocal & Exit /B %ErrorLevel%
#>
$AuditLog = Get-DhcpServerAuditLog
if ($AuditLog.Enable) {
Write-Output "File '$($AuditLog.Path)\Dhcp*SrvLog-*.log'"
}
else {
[Console]::Error.WriteLine(@"
DHCP audit logging is disabled. To enable, run in PowerShell:
> Set-DhcpServerAuditLog -Enable $True
"@)
exit 1
}
Collecting DHCP server logs from Windows Event Log
Events are also written to three logs in the Windows Event Log.
To make sure the required logs are enabled, open Event Viewer (eventvwr
) and check the logs under Applications and Services Logs > Microsoft > Windows > DHCP-Server.
To enable a log, right-click on it and click Enable Log.
Alternatively, the following PowerShell script will check all three DHCP logs, enabling if necessary.
$LogNames = @("DhcpAdminEvents",
"Microsoft-Windows-Dhcp-Server/FilterNotifications",
"Microsoft-Windows-Dhcp-Server/Operational")
ForEach ($LogName in $LogNames) {
$EventLog = Get-WinEvent -ListLog $LogName
if ($EventLog.IsEnabled) {
Write-Host "Already enabled: $LogName"
}
else {
Write-Host "Enabling: $LogName"
$EventLog.IsEnabled = $true
$EventLog.SaveChanges()
}
}
This configuration uses the im_msvistalog module to collect DHCP Server event logs from the DhcpAdminEvents
, FilterNotifications
, and Operational
logs.
<Input dhcp_server_eventlog>
Module im_msvistalog
<QueryXML>
<QueryList>
<Query Id="0">
<Select Path="DhcpAdminEvents">*</Select>
<Select Path="Microsoft-Windows-Dhcp-Server/FilterNotifications">
*</Select>
<Select Path="Microsoft-Windows-Dhcp-Server/Operational">*</Select>
</Query>
</QueryList>
</QueryXML>
</Input>