Return to
Portfolio

56.3. Windows DHCP Server

DHCP Server events are written to DHCP audit log files (if configured) and to the Windows EventLog. This section provides details about configuring logging and collecting logs with NXLog.

Note
The following sections have been tested on Windows Server 2016.

56.3.1. DHCP Server Audit Logging

The Windows DHCP Server provides an audit logging feature that writes server activity to log files. NXLog 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.

IPv4 Log Sample (many header lines omitted)
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
IPv6 Log Sample (many header lines omitted)
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.

Note
The default audit log path, C:\Windows\System32\dhcp, is architecture-specific. To collect DHCP audit logs using a 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 the NXLog agent is running on the system’s native architecture, it is not necessary to change the log file location from the default.
56.3.1.1. Configuring via PowerShell
  1. 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
  2. To set the audit log configuration, run this command (see Set-DhcpServerAuditLog on Microsoft Docs).

    > Set-DhcpServerAuditLog -Enable $True -Path C:\dhcp
  3. The DHCP server must be restarted for the configuration changes to take effect.

    > Restart-Service DHCPServer
56.3.1.2. Configuring With the DHCP Management Console

Follow these steps to configure the DHCP audit log. Any changes to the audit log settings apply to both IPv4 and IPv6, once the DHCP server has been restarted.

  1. Run the DHCP MMC snap-in (dhcpmgmt.msc), expand the server for which to configure logging, and click on IPv4.

    DHCP Management MMC snap-in
  2. 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.

    IPv4 Properties, General
  3. Make sure Enable DHCP audit logging is checked.

  4. Open the Advanced tab, change the Audit log file path, and click OK.

    IPv4 Properties, Advanced
  5. Restart the DHCP server by right-clicking the server and clicking All Tasks  Restart.

56.3.1.3. Collecting DHCP Server Audit Logs

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.

Example 231. Collecting and Parsing DHCP Audit Events

This configuration uses a short batch/PowerShell polyglot script with the include_stdout directive to fetch the DHCP audit log location. The im_file module reads from the files 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.

Note
If DHCP audit logging is disabled, the script will print an error and NXLog will abort during the configuration check.
nxlog.conf [Download file]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<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>
dhcp_server_audit_include.cmd [Download file]
@( 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
}

56.3.2. DHCP Server EventLog

Events are also written to three logs in the EventLog. 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.

Enabling DHCP Client Logs

Alternatively, the following PowerShell script will check all three 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()
    }
}
Example 232. Collecting DHCP Server Events From the EventLog

This configuration uses the im_msvistalog module to collect DHCP Server events from the EventLog DhcpAdminEvents, FilterNotifications, and Operational logs.

nxlog.conf [Download file]
1
2
3
4
5
6
7
8
9
10
11
12
13
<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>