NXLog Docs

IBM QRadar SIEM

IBM QRadar Security Information and Event Management (SIEM) collects event data and uses analytics, correlation, and threat intelligence features to identify known or potential threats, provide alerting and reports, and aid in incident investigations. For more information, see IBM QRadar SIEM on IBM.com.

NXLog can be configured to collect events and forward them to QRadar SIEM. This chapter provides information about setting up this integration, both for generic structured logs and for several specific log types. The last section shows output examples for forwarding the processed logs to QRadar.

Setting up the QRadar appliance

Several tasks may be required to prepare IBM QRadar for receiving events from NXLog.

QRadar dependencies and system configuration

Adding a TLS Syslog log source

Events can be sent to QRadar securely with TLS. With these instructions, the NXLog agent(s) will verify the authenticity of the QRadar receiver and encrypt event data in transit. This requires that appropriate certificates be created and a separate TLS Syslog "listener" log source be added on QRadar.

This log source will act as a gateway, passing each event on to another matching log source. Only one TLS listener is required per port; see Multiple log sources over TLS syslog in the IBM QRadar documentation.

First, prepare the TLS certificate and key files (for more information, see OpenSSL certificate creation):

  1. Locate a certificate authority (CA) certificate and private key, or generate and sign a new one. The CA certificate (for example, rootCA.pem) will be used by the NXLog agent to authenticate the QRadar receiver in Forwarding logs below.

  2. Create a certificate and private key for QRadar TLS Syslog (for example, server.crt and server.key).

  3. Convert the QRadar private key to a DER-encoded PKCS8 key (see QRadar: TLS Syslog support of DER-encoded PKCS8 custom certificates):

    $ openssl pkcs8 -topk8 -inform PEM -outform DER -in server.key \
          -out server.key.der -nocrypt
  4. Copy the private key and certificate files to QRadar (the steps below assume the files are copied to /root/server.*).

Then add the log source on QRadar:

  1. In the QRadar web interface, go to Menu > Admin > Data Sources > Events > Log Sources.

    ibm qradar log sources icon
  2. Click Add to add a new log source. The Add a log source window appears.

    ibm qradar add log source
  3. Enter a Log Source Name and, optionally, a Log Source Description.

  4. For the Log Source Type, select Universal DSM.

  5. For the Protocol Configuration, select TLS Syslog.

  6. As the Log Source Identifier, enter the source device IP address or hostname. For multiple log sources, any identifier can be used here.

  7. For Certificate Type, select Provide Certificate.

  8. Set Provided Server Certificate Path to the path of the server certificate (for example, /root/server.crt).

  9. Set Provided Private Key Path to the path of the DER-encoded server key (for example, /root/server.key.der).

  10. Select the Target Event Collector. Use this to poll for and process events using the specified event collector, rather than on the Console appliance.

  11. Make any other changes required, and then click Save.

  12. Go to Menu > Admin and click Advanced > Deploy Full Configuration after making all required log source changes.

Adding a QRadar log source

Follow these steps to add a new log source to QRadar SIEM. This will need to be done once for each log source, using the correct Log Source Type for each.

  1. In the QRadar web interface, go to Menu > Admin > Data Sources > Events > Log Sources.

    ibm qradar log sources icon
  2. Click Add to add a new log source. The Add a log source window appears.

    ibm qradar add log source 2
  3. Enter a Log Source Name and, optionally, a Log Source Description.

  4. Select a Log Source Type. Consult the sections below for the correct log type to use for each source.

  5. For the Protocol Configuration, select Syslog.

  6. As the Log Source Identifier, enter the source system’s IP address.

    The Syslog hostname field is used by QRadar as the log source identifier to associate events with a particular log source when received. This value can be adjusted by changing the $Hostname = host_ip(); line in the examples below: keep the line as-is to use the system’s first non-loopback IP address, remove the line to use the system hostname, or set the line to a custom value (for example, $Hostname = "myhostname";).
  7. Select the Target Event Collector. Use this to poll for and process events using the specified event collector, rather than on the Console appliance.

  8. Make any other changes required, and then click Save.

  9. Go to Menu > Admin and click Advanced > Deploy Full Configuration after making all required log source changes.

Sending generic structured logs to QRadar

NXLog can be configured to send generic structured logs to QRadar using Log Event Extended Format (LEEF). The xm_leef to_leef() procedure will generate LEEF events using certain NXLog fields for the event header and all remaining fields as event attributes.

LEEF has several predefined event attributes that should be used where applicable—see LEEF event components and Predefined LEEF event attributes on IBM Knowledge Center. These fields can be set during parsing, set to static values manually ($usrName = "john";), renamed using the rename_field() directive, or renamed using the xm_rewrite Rename directive (NXLog Enterprise Edition only). Additionally, to_leef() will set several predefined attributes automatically.

Use Universal LEEF as QRadar’s Log Source Type. Once LEEF events have been received by QRadar, specific fields can be selected for extraction as described in the IBM QRadar documentation on Writing an expression for structured data in LEEF format. LEEF events can also be mapped to QRadar Identifiers (QIDs). For more information, see the Universal LEEF section in the QRadar DSM Guide.

Example 1. Sending LEEF logs to QRadar

This example reads Syslog messages from file, parses them, and sets some additional fields. Then the xm_leef to_leef() procedure is used to convert the event to LEEF (and write it to the $raw_event field). Because the event is converted in the scope of this input instance, it is not necessary to do additional processing in the corresponding output instance—see Forwarding logs for output examples that could be used to send the events to QRadar.

This example is intended as a starting point for a configuration that provides a specific set of fields to QRadar. For logs that are already structured, it may only be necessary to rename a few fields according to the predefined LEEF attribute names.
Input sample (auth.log)
Jul 31 07:17:01 debian CRON[968]: pam_unix(cron:session): session opened for user root by (uid=0)
Aug 11 22:43:26 debian sshd[5584]: Invalid user baduser from 10.80.0.1 port 33122
nxlog.conf
<Extension _leef>
    Module  xm_leef
</Extension>

<Extension _syslog>
    Module  xm_syslog
</Extension>

<Input auth>
    Module  im_file
    File    '/var/log/auth.log'
    <Exec>
        # Parse Syslog event and set fields in the event record
        parse_syslog();

        # Set event category and event ID (for QID mapping)
        if $Message =~ /^Invalid/
        {
            $Category = "Failed";
            $EventID = "Logon Failure";
        }
        else
        {
            $Category = "Success";
            $EventID = "Logon Success";
        }

        # Extract user name for "usrName" event attribute
        $Message =~ /user (?<usrName>\S+)/;

        # Set $AccountType based on whether the message mentions the root user;
        # this is mapped to the "role" event attribute
        if $usrName == "root" $AccountType = "Administrator";
        else $AccountType = "User";

        # Use the first non-loopback IP address as the log source identifier
        $Hostname = host_ip();

        # Convert to LEEF
        to_leef();
    </Exec>
</Input>
Output sample
<13>Jul 31 07:17:01 10.80.1.49 CRON[968]: LEEF:1.0|NXLog|CRON|4.4.4347|Logon Success|EventReceivedTime=2019-08-11 22:48:59	SourceModuleName=file	SourceModuleType=im_file	SyslogFacilityValue=1	SyslogFacility=USER	SyslogSeverityValue=5	SyslogSeverity=NOTICE	sev=2	Severity=INFO	identHostName=debian	devTime=2019-07-31 07:17:01	vSrcName=CRON	ProcessID=968	Message=pam_unix(cron:session): session opened for user root by (uid=0)	cat=Success	EventID=Logon Success	usrName=root	role=Administrator	devTimeFormat=yyyy-MM-dd HH:mm:ss
<13>Aug 11 22:43:26 10.80.1.49 sshd[5584]: LEEF:1.0|NXLog|sshd|4.4.4347|Logon Failure|EventReceivedTime=2019-08-11 22:48:59	SourceModuleName=file	SourceModuleType=im_file	SyslogFacilityValue=1	SyslogFacility=USER	SyslogSeverityValue=5	SyslogSeverity=NOTICE	sev=2	Severity=INFO	identHostName=debian	devTime=2019-08-11 22:43:26	vSrcName=sshd	ProcessID=5584	Message=Invalid user baduser from 10.80.0.1 port 33122	cat=Failed	EventID=Logon Failure	usrName=baduser	role=User	devTimeFormat=yyyy-MM-dd HH:mm:ss

Sending specific log types for QRadar to parse

To take full advantage of QRadar’s parsing of specific log types, NXLog can be configured to send logs using the specific format expected by the corresponding QRadar DSM. In each case, events are collected, parsed, and converted to a tab-delimited key-value pair format that QRadar expects.

Microsoft DHCP Server

To send DHCP Server audit log events to QRadar SIEM, set up DHCP Audit Logging and use the NXLog configuration shown below. If QRadar does not auto-discover the log source, add one manually. The Log Source Type should be set to Microsoft DHCP Server and the Protocol Configuration should be set to Syslog—see Adding a QRadar log source.

For more information, see DHCP server audit logging and the Microsoft DHCP Server page in the QRadar DSM Guide.

Example 2. Sending Windows DHCP logs to QRadar

In this example, NXLog is configured to read logs from the following paths:

  • C:\Windows\System32\dhcp\DhcpSrvLog-*.log

  • C:\Windows\System32\dhcp\DhcpV6SrvLog-*.log

NXLog parses the events and converts the structured data for forwarding to QRadar.

Input sample (DhcpSrvLog)
13,07/31/19,07:18:29,Conflict,10.80.2.1,BAD_ADDRESS,,,0,6,,,,,,,,,0
Input sample (DhcpV6SrvLog)
11004,07/31/19,07:32:34,DHCPV6 Renew,2001:db8::667a:1521:96ab:5f50,QRADARWIN.nxlog.org,,14,00010001244AC14F5254005DF4CC,,,,,
nxlog.conf
<Extension _syslog>
    Module  xm_syslog
</Extension>

<Extension dhcp_csv_parser>
    Module  xm_csv
    Fields  ID, Date, Time, Description, IPAddress, LogHostname, 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, IPAddress, LogHostname, MACAddress, \
            UserName, TransactionID, QResult, ProbationTime, CorrelationID, \
            DHCID, VendorClassHex
</Extension>

<Input dhcp>
    Module  im_file
    File    'C:\Windows\System32\dhcp\DhcpSrvLog-*.log'
    File    'C:\Windows\System32\dhcp\DhcpV6SrvLog-*.log'
    <Exec>
        # Only process lines that begin with an event ID
        if $raw_event =~ /^\d+,/
        {
            if file_name() =~ /^.*\\(.*)$/ $FileName = $1;
            if $FileName =~ /DhcpSrvLog-/
            {
                dhcp_csv_parser->parse_csv();
                $Message = "AgentDevice=WindowsDHCP" +
                    "\tAgentLogFile=" + $FileName +
                    "\tID=" + $ID +
                    "\tDate=" + $Date +
                    "\tTime=" + $Time +
                    "\tDescription=" + $Description +
                    "\tIP Address=" + $IPAddress +
                    "\tHost Name=" + $LogHostname +
                    "\tMAC Address=" + $MACAddress +
                    "\tUser Name=" + $UserName +
                    "\tTransactionID=" + $TransactionID +
                    "\tQResult=" + $QResult +
                    "\tProbationtime=" + $ProbationTime +
                    "\tCorrelationID=" + $CorrelationID +
                    "\tDhcid=" + $DHCID +
                    "\tVendorClass(Hex)=" + $VendorClassHex +
                    "\tVendorClass(ASCII)=" + $VendorClassASCII +
                    "\tUserClass(Hex)=" + $UserClassHex +
                    "\tUserClass(ASCII)=" + $UserClassASCII +
                    "\tRelayAgentInformation=" + $RelayAgentInformation +
                    "\tDnsRegError=" + $DnsRegError;
            }
            else
            {
                dhcpv6_csv_parser->parse_csv();
                $Message = "AgentDevice=WindowsDHCP" +
                    "\tAgentLogFile=" + $FileName +
                    "\tID=" + $ID +
                    "\tDate=" + $Date +
                    "\tTime=" + $Time +
                    "\tDescription=" + $Description +
                    "\tIP Address=" + $IPAddress +
                    "\tHost Name=" + $LogHostname +
                    "\tMAC Address=" + $MACAddress +
                    "\tUser Name=" + $UserName +
                    "\tTransactionID=" + $TransactionID +
                    "\tQResult=" + $QResult +
                    "\tProbationtime=" + $ProbationTime +
                    "\tCorrelationID=" + $CorrelationID +
                    "\tDhcid=" + $DHCID +
                    "\tVendorClass(Hex)=" + $VendorClassHex;
            }
            $EventTime = strptime($Date + ' ' + $Time, '%m/%d/%y %H:%M:%S');
            $Hostname = host_ip();
            to_syslog_bsd();
        }
        # Discard header lines (which do not begin with an event ID)
        else drop();
    </Exec>
</Input>
Output sample (DhcpSrvLog)
<13>Jul 31 07:18:29 10.80.1.49 AgentDevice=WindowsDHCP	AgentLogFile=DhcpSrvLog-Wed.log	ID=13	Date=07/31/19	Time=07:18:29	Description=Conflict	IP Address=10.80.2.1	Host Name=BAD_ADDRESS	MAC Address=	User Name=	TransactionID=0	QResult=6	Probationtime=	CorrelationID=	Dhcid=	VendorClass(Hex)=	VendorClass(ASCII)=	UserClass(Hex)=	UserClass(ASCII)=	RelayAgentInformation=	DnsRegError=0

DNS debug log

To send DNS debug log events to QRadar, enable debug logging and use the NXLog configuration shown below.

Do not enable Details in the DNS Server Debug Logging dialog.

If QRadar does not auto-discover the log source, add one manually. The Log Source Type should be set to Microsoft DNS Debug and the Protocol Configuration should be set to Syslog—see Adding a QRadar log source. If the Microsoft DNS Debug log source type is not available, see Setting up the QRadar appliance above.

For more information, see Windows DNS Server and the Microsoft DNS Debug page in the QRadar DSM Guide.

Example 3. Sending DNS debug logs to QRadar

This configuration uses the xm_msdns extension module to parse the Windows DNS debug log.

nxlog.conf
<Extension _syslog>
    Module  xm_syslog
</Extension>

<Extension dns_parser>
    Module  xm_msdns
</Extension>

<Input dns>
    Module      im_file
    File        'C:\logs\dns.log'
    InputType   dns_parser
    <Exec>
        $raw_event =~ /(?x)^(?<Date>\d+\/\d+\/\d+)\s(?<Time>\d+:\d+:\d+\s+\w{2})/;
        if file_name() =~ /^.*\\(.*)$/ $FileName = $1;
        $Message = "AgentDevice=WindowsDNS" +
            "\tAgentLogFile=" + $FileName +
            "\tDate=" + $Date +
            "\tTime=" + $Time +
            "\tThread ID=" + $ThreadID;
        if $Context == "EVENT"
        {
            $EventDescription =~ s/,//g;
            $Message = $Message +
                "\tContext=EVENT" +
                "\tMessage=" + $EventDescription;
        }
        else if $Context == "Note"
        {
            $Note =~ s/^Note: //;
            $Note =~ s/, / /g;
            $Message = $Message +
                "\tContext=NOTE" +
                "\tMessage=" + $Note;
        }
        else
        # $Context == "PACKET"
        {
            $FlagsChar = "";
            if $AuthoritativeAnswer $FlagsChar = "A";
            if $TruncatedResponse $FlagsChar = $FlagsChar + "T";
            if $RecursionDesired $FlagsChar = $FlagsChar + "D";
            if $RecursionAvailable $FlagsChar = $FlagsChar + "R";
            if $QueryResponseIndicator == "Query" $QueryResponse = "Q";
            else if $QueryResponseIndicator == "Response" $QueryResponse = "R";
            if $Opcode == "Standard Query" $OpcodeStr = "Q";
            else if $Opcode == "Notify" $OpcodeStr = "N";
            else if $Opcode == "Update" $OpcodeStr = "U";
            else if $Opcode == "Unknown" $OpcodeStr = "?";
            $Message = $Message +
                "\tContext=PACKET" +
                "\tMessage=" +
                "\tInternal packet identifier=" + $InternalPacketIdentifier +
                "\tUDP/TCP indicator=" + $Protocol +
                "\tSend/Receive indicator=" + $SendReceiveIndicator +
                "\tRemote IP=" + $RemoteIP +
                "\tXid (hex)=" + $Xid +
                "\tQuery/Response=" + $QueryResponse +
                "\tOpcode=" + $OpcodeStr +
                "\tFlags (hex)=" + $FlagsHex +
                "\tFlags (char codes)=" + $FlagsChar +
                "\tResponseCode=" + $ResponseCode +
                "\tQuestion Type=" + $QuestionType +
                "\tQuestion Name=" + $QuestionName;
        }
        $Hostname = host_ip();
        to_syslog_bsd();
    </Exec>
</Input>
Output sample
<13>Jul 20 08:42:07 10.80.1.49 AgentDevice=WindowsDNS	AgentLogFile=debug.log	Date=7/20/2019	Time=8:42:07 AM	Thread ID=0710	Context=EVENT	Message=The DNS server has finished the background loading of zones. All zones are now available for DNS updates and zone transfers as allowed by their individual zone configuration.

Microsoft Exchange Server

Microsoft Exchange Server logs can be collected and sent to QRadar SIEM as shown below.

QRadar does not support auto-discovery for Exchange logs, so it is necessary to add a log source manually. The Log Source Type should be set to Microsoft Exchange Server and the Protocol Configuration should be set to Syslog—see Adding a QRadar log source.

For more information, see the Microsoft Exchange chapter and the Microsoft Exchange Server pages in the QRadar DSM Guide.

Example 4. Sending Exchange logs to QRadar

The following configuration uses the im_file module to read message tracking, Outlook web access (OWA), and SMTP logs from various paths. The logs are parsed and converted for forwarding to QRadar.

Make sure to use the correct ID for the Exchange Back End site. This can be verified using the Internet Information Services (IIS) Manager. The following example collects logs from the site with ID 2 (W3SVC2/).
nxlog.conf
<Extension _syslog>
    Module  xm_syslog
</Extension>

<Extension w3c_parser>
    Module  xm_w3c
</Extension>

<Extension w3c_comma_parser>
    Module      xm_w3c
    Delimiter   ,
</Extension>

<Input exchange_OWA>
    Module      im_file
    File        'C:\inetpub\logs\LogFiles\W3SVC2\u_ex*.log'
    InputType   w3c_parser
    <Exec>
        if file_name() =~ /^.*\\(.*)$/ $FileName = $1;
        if ${cs-uri-query} == undef ${cs-uri-query} = "-";
        if ${cs-username} == undef ${cs-username} = "-";
        if ${cs(Referer)} == undef ${cs(Referer)} = "-";
        $Message = "AgentDevice=MicrosoftExchange" +
            "\tAgentLogFile=" + $FileName +
            "\tAgentLogFormat=W3C" +
            "\tAgentLogProtocol=OWA" +
            "\tdate=" + $date +
            "\ttime=" + $time +
            "\ts-ip=" + ${s-ip} +
            "\tcs-method=" + ${cs-method} +
            "\tcs-uri-stem=" + ${cs-uri-stem} +
            "\tcs-uri-query=" + ${cs-uri-query} +
            "\ts-port=" + ${s-port} +
            "\tcs-username=" + ${cs-username} +
            "\tc-ip=" + ${c-ip} +
            "\tcs(User-Agent)=" + ${cs(User-Agent)} +
            "\tcs(Referer)=" + ${cs(Referer)} +
            "\tsc-status=" + ${sc-status} +
            "\tsc-substatus=" + ${sc-substatus} +
            "\tsc-win32-status=" + ${sc-win32-status} +
            "\ttime-taken=" + ${time-taken};
        $EventTime = parsedate($date + " " + $time);
        $Hostname = host_ip();
        delete($SourceName);
        to_syslog_bsd();
    </Exec>
</Input>

define BASEDIR C:\Program Files\Microsoft\Exchange Server\V15\TransportRoles

<Input exchange_MessageTracking>
    Module      im_file
    File        '%BASEDIR%\Logs\MessageTracking\MSGTRK*.LOG'
    InputType   w3c_comma_parser
    <Exec>
        if file_name() =~ /^.*\\(.*)$/ $FileName = $1;
        ${message-info} =~ s/\s+$//g;
        $Message = "AgentDevice=MicrosoftExchange" +
            "\tAgentLogFile=" + $FileName +
            "\tAgentLogFormat=MSGTRK" +
            "\tAgentLogProtocol=MT" +
            "\tdate-time=" + ${date-time} +
            "\tclient-ip=" + ${client-ip} +
            "\tclient-hostname=" + ${client-hostname} +
            "\tserver-ip=" + ${server-ip} +
            "\tserver-hostname=" + ${server-hostname} +
            "\tsource-context=" + ${source-context} +
            "\tconnector-id=" + ${connector-id} +
            "\tsource=" + $source +
            "\tevent-id=" + ${event-id} +
            "\tinternal-message-id=" + ${internal-message-id} +
            "\tmessage-id=" + ${message-id} +
            "\tnetwork-message-id=" + ${network-message-id} +
            "\trecipient-address=" + ${recipient-address} +
            "\trecipient-status=" + ${recipient-status} +
            "\ttotal-bytes=" + ${total-bytes} +
            "\trecipient-count=" + ${recipient-count} +
            "\trelated-recipient-address=" + ${related-recipient-address} +
            "\treference=" + $reference +
            "\tmessage-subject=" + ${message-subject} +
            "\tsender-address=" + ${sender-address} +
            "\treturn-path=" + ${return-path} +
            "\tmessage-info=" + ${message-info} +
            "\tdirectionality=" + $directionality +
            "\ttenant-id=" + ${tenant-id} +
            "\toriginal-client-ip=" + ${original-client-ip} +
            "\toriginal-server-ip=" + ${original-server-ip} +
            "\tcustom-data=" + ${custom-data} +
            "\ttransport-traffic-type=" + ${transport-traffic-type} +
            "\tlog-id=" + ${log-id} +
            "\tschema-version=" + ${schema-version};
        $EventTime = parsedate(${date-time});
        $Hostname = host_ip();
        delete($SourceName);
        to_syslog_bsd();
    </Exec>
</Input>

<Input exchange_SMTP>
    Module      im_file
    File        '%BASEDIR%\Logs\Hub\ProtocolLog\SmtpReceive\RECV*.LOG'
    File        '%BASEDIR%\Logs\Hub\ProtocolLog\SmtpSend\SEND*.LOG'
    InputType   w3c_comma_parser
    <Exec>
        if file_name() =~ /^.*\\(.*)$/ $FileName = $1;
        if $event == undef $event = "-";
        $Message = "AgentDevice=MicrosoftExchange" +
            "\tAgentLogFile=" + $FileName +
            "\tAgentLogFormat=SMTP" +
            "\tAgentLogProtocol=SMTP" +
            "\tdate-time=" + ${date-time} +
            "\tconnector-id=" + ${connector-id} +
            "\tsession-id=" + ${session-id} +
            "\tsequence-number=" + ${sequence-number} +
            "\tlocal-endpoint=" + ${local-endpoint} +
            "\tremote-endpoint=" + ${remote-endpoint} +
            "\tevent=" + $event +
            "\tdata=" + $data +
            "\tcontext=" + $context;
        $EventTime = parsedate(${date-time});
        $Hostname = host_ip();
        delete($SourceName);
        to_syslog_bsd();
    </Exec>
</Input>
Output sample (SMTPReceive)
<13>Jul 27 23:35:09 10.80.1.49 AgentDevice=MicrosoftExchange	AgentLogFile=RECV2019072723-1.LOG	AgentLogFormat=SMTP	AgentLogProtocol=SMTP	date-time=2019-07-27T23:35:09.647Z	connector-id=QRADARWIN\Default QRADARWIN	session-id=08D7122B7BADF0F4	sequence-number=1	local-endpoint=10.80.1.49:2525	remote-endpoint=10.80.1.49:21408	event=>	data=220 QRADARWIN.nxlog.org Microsoft ESMTP MAIL Service ready at Sat, 27 Jul 2019 23:35:08 +0000	context=

Microsoft IIS

Microsoft IIS logs can be collected using the W3C Extended Log File Format. The W3C logging should be configured as described in the Configuring Microsoft IIS by using the IIS Protocol page of the QRadar DSM Guide.

For NXLog Community Edition, the xm_csv module can be used instead of xm_w3c.

If QRadar does not auto-discover the log source, add one manually. The Log Source Type should be set to Microsoft IIS and the Protocol Configuration should be set to Syslog—see Adding a QRadar log source.

For more information, see the Microsoft IIS chapter and the QRadar DSM Guide Microsoft IIS Server pages.

Example 5. Sending Windows IIS logs to QRadar

This configuration uses the xm_w3c extension module to parse the IIS log, and converts the events to a tab-delimited format for QRadar.

Input sample
2019-07-24 09:21:55 127.0.0.1 POST /OWA/auth.owa &CorrelationID=<empty>;&cafeReqId=4b9353b7-e17b-4bc5-9e54-bc6b4733d6dd;&encoding=; 443 HealthMailboxa733ff32a90d44bb970f7a147fb3f328@nxlog.org 127.0.0.1 AMProbe/Local/ClientAccess - 302 0 0 10171
nxlog.conf
<Extension _syslog>
    Module  xm_syslog
</Extension>

<Extension w3c_parser>
    Module  xm_w3c
</Extension>

<Input iis>
    Module      im_file
    File        'C:\inetpub\logs\LogFiles\W3SVC1\u_ex*.log'
    InputType   w3c_parser
    <Exec>
        if file_name() =~ /^.*\\(.*)$/ $FileName = $1;
        if ${cs-uri-query} == undef ${cs-uri-query} = "-";
        if ${cs-username} == undef ${cs-username} = "-";
        if ${cs(Referer)} == undef ${cs(Referer)} = "-";
        $Message = "AgentDevice=MSIIS" +
            "\tAgentLogFile=" + $FileName +
            "\tAgentLogFormat=W3C" +
            "\tAgentLogProtocol=W3C" +
            "\tdate=" + $date +
            "\ttime=" + $time +
            "\ts-ip=" + ${s-ip} +
            "\tcs-method=" + ${cs-method} +
            "\tcs-uri-stem=" + ${cs-uri-stem} +
            "\tcs-uri-query=" + ${cs-uri-query} +
            "\ts-port=" + ${s-port} +
            "\tcs-username=" + ${cs-username} +
            "\tc-ip=" + ${c-ip} +
            "\tcs(User-Agent)=" + ${cs(User-Agent)} +
            "\tcs(Referer)=" + ${cs(Referer)} +
            "\tsc-status=" + ${sc-status} +
            "\tsc-substatus=" + ${sc-substatus} +
            "\tsc-win32-status=" + ${sc-win32-status} +
            "\ttime-taken=" + ${time-taken};
        $EventTime = parsedate($date + " " + $time);
        $Hostname = host_ip();
        delete($SourceName);
        to_syslog_bsd();
    </Exec>
</Input>
Output sample
<13>Jul 24 09:21:55 10.80.1.49 AgentDevice=MSIIS	AgentLogFile=u_ex190724.log	AgentLogFormat=W3C	AgentLogProtocol=W3C	date=2019-07-24	time=09:21:55	s-ip=127.0.0.1	cs-method=POST	cs-uri-stem=/OWA/auth.owa	cs-uri-query=&CorrelationID=<empty>;&cafeReqId=4b9353b7-e17b-4bc5-9e54-bc6b4733d6dd;&encoding=;	s-port=443	cs-username=HealthMailboxa733ff32a90d44bb970f7a147fb3f328@nxlog.org	c-ip=127.0.0.1	cs(User-Agent)=AMProbe/Local/ClientAccess	cs(Referer)=-	sc-status=302	sc-substatus=0	sc-win32-status=0	time-taken=10171

Microsoft SQL

Microsoft SQL logs can be collected using the xm_charconv and im_file modules.

If QRadar does not auto-discover the log source, add one manually. The Log Source Type should be set to Microsoft SQL Server and the Protocol Configuration should be set to Syslog—see Adding a QRadar log source.

For configuration information, see the Microsoft SQL Server section in the QRadar DSM Guide.

Example 6. Sending Microsoft SQL logs to QRadar

This example reads and parses events from the SQL Server log file, then converts the events to a tab-delimited format for QRadar.

nxlog.conf
<Extension _syslog>
    Module      xm_syslog
</Extension>

<Extension charconv>
    Module      xm_charconv
    LineReader  UTF-16LE
</Extension>

define ERRORLOG_EVENT /(?x)(?<Date>\d+-\d+-\d+)\s \
                           (?<Time>\d+:\d+:\d+.\d+)\s \
                           (?<Source>\S+)\s+ \
                           (?<Payload>.+)$/s

<Input sql>
    Module      im_file
    File        'C:\Program Files\Microsoft SQL Server\' + \
                    'MSSQL14.MSSQLSERVER\MSSQL\Log\ERRORLOG'
    InputType   charconv
    <Exec>
        # Attempt to match regular expression
        if $raw_event =~ %ERRORLOG_EVENT%
        {
            # Check if previous lines were saved
            if defined(get_var('saved'))
            {
                $tmp = $raw_event;
                $raw_event = get_var('saved');
                set_var('saved', $tmp);
                delete($tmp);

                # Process and send previous event
                $raw_event =~ %ERRORLOG_EVENT%;
                if file_name() =~ /^.*\\(.*)$/ $FileName = $1;
                $Payload =~ s/\t/ /g;
                $Payload =~ s/\s*$//;
                $Message = "AgentDevice=MSSQL" +
                    "\tAgentLogFile=" + $FileName +
                    "\tDate=" + $Date +
                    "\tTime=" + $Time +
                    "\tSource=" + $Source +
                    "\tMessage=" + $Payload;
                $EventTime = parsedate($Date + " " + $Time);
                $Hostname = host_ip();
                to_syslog_bsd();
            }
            # Save this line to module variable until the next event
            else
            {
                set_var('saved', $raw_event);
                drop();
            }
        }
        # Not the first line of the event; save to module variable
        else
        {
            set_var('saved', get_var('saved') + " " + $raw_event);
            drop();
        }
    </Exec>
</Input>
Output sample
<13>Aug 21 22:55:36 10.80.1.49 AgentDevice=MSSQL	AgentLogFile=ERRORLOG	Date=2019-08-21	Time=22:55:36.23	Source=spid16s	Message=The Service Broker endpoint is in disabled or stopped state.

Windows Event Log

To send Windows logs to QRadar, use the im_msvistalog module and convert the events to a tab-delimited key-value pair format supported by the corresponding QRadar DSM.

This format is recommended instead of Snare or Log Event Extended Format (LEEF) in order to take full advantage of the parsing provided by the QRadar DSM. Otherwise additional parsing and/or mappings would be required to translate Windows event fields to QRadar fields.

If QRadar does not auto-discover the log source, add one manually. The Log Source Type should be set to Microsoft Windows Security Event Log and the Protocol Configuration should be set to Syslog—see Adding a QRadar log source.

For more information, see the Windows Event Log chapter and the Microsoft Windows Security Event Log section in the QRadar DSM Guide.

Example 7. Sending Windows events to QRadar

This configuration will collect events from Windows Event Log using im_msvistalog, convert the $Message field to a specific tab-delimited format, and add a BSD Syslog header with xm_syslog.

This example does not filter events, but forwards all events to QRadar. Only a subset of those events will be recognized and parsed by the QRadar DSM. For more information about using Windows Event Log queries to limit collected events, see Windows Event Log.
nxlog.conf
<Extension syslog>
    Module    xm_syslog
</Extension>

<Input eventlog>
    Module    im_msvistalog
    <QueryXML>
        <QueryList>
            <Query Id='0'>
                <Select Path='Application'>*</Select>
                <Select Path='Security'>*[System/Level&lt;4]</Select>
                <Select Path='System'>*</Select>
                <Select Path='Microsoft-Windows-Sysmon/Operational'>*</Select>
                <Select Path='Microsoft-Windows-PowerShell/Operational'>*</Select>
                <Select Path='Windows PowerShell'>*</Select>
            </Query>
        </QueryList>
    </QueryXML>
    <Exec>
        if $Category == undef $Category = 0;
        if $EventType == 'CRITICAL'
        {
            $EventTypeNum = 1;
            $EventTypeStr = "Critical";
        }
        else if $EventType == 'ERROR'
        {
            $EventTypeNum = 2;
            $EventTypeStr = "Error";
        }
        else if $EventType == 'INFO'
        {
            $EventTypeNum = 4;
            $EventTypeStr = "Informational";
        }
        else if $EventType == 'WARNING'
        {
            $EventTypeNum = 3;
            $EventTypeStr = "Warning";
        }
        else if $EventType == 'VERBOSE'
        {
            $EventTypeNum = 5;
            $EventTypeStr = "Verbose";
        }
        else
        {
            $EventTypeNum = 0;
            $EventTypeStr = "Audit";
        }
        if $OpcodeValue == 0 $Opcode = "Info";
        if $TaskValue == 0 $TaskValue = "None";

        $EpochTime = string(integer($EventTime));
        $EpochTime =~ /^(?<sec>\d+)(?<ms>\d{6})$/;
        $EpochTime = $sec;

        if $TaskValue == 12288 { $TaskStr = "SE_ADT_SYSTEM_SECURITYSTATECHANGE"; }
        else if $TaskValue == 12289 { $TaskStr = "SE_ADT_SYSTEM_SECURITYSUBSYSTEMEXTENSION"; }
        else if $TaskValue == 12290 { $TaskStr = "SE_ADT_SYSTEM_INTEGRITY"; }
        else if $TaskValue == 12291 { $TaskStr = "SE_ADT_SYSTEM_IPSECDRIVEREVENTS"; }
        else if $TaskValue == 12292 { $TaskStr = "SE_ADT_SYSTEM_OTHERS"; }
        else if $TaskValue == 12544 { $TaskStr = "SE_ADT_LOGON_LOGON"; }
        else if $TaskValue == 12545 { $TaskStr = "SE_ADT_LOGON_LOGOFF"; }
        else if $TaskValue == 12546 { $TaskStr = "SE_ADT_LOGON_ACCOUNTLOCKOUT"; }
        else if $TaskValue == 12547 { $TaskStr = "SE_ADT_LOGON_IPSECMAINMODE"; }
        else if $TaskValue == 12548 { $TaskStr = "SE_ADT_LOGON_SPECIALLOGON"; }
        else if $TaskValue == 12549 { $TaskStr = "SE_ADT_LOGON_IPSECQUICKMODE"; }
        else if $TaskValue == 12550 { $TaskStr = "SE_ADT_LOGON_IPSECUSERMODE"; }
        else if $TaskValue == 12551 { $TaskStr = "SE_ADT_LOGON_OTHERS"; }
        else if $TaskValue == 12552 { $TaskStr = "SE_ADT_LOGON_NPS"; }
        else if $TaskValue == 12553 { $TaskStr = "SE_ADT_LOGON_CLAIMS"; }
        else if $TaskValue == 12554 { $TaskStr = "SE_ADT_LOGON_GROUPS"; }
        else if $TaskValue == 12800 { $TaskStr = "SE_ADT_OBJECTACCESS_FILESYSTEM"; }
        else if $TaskValue == 12801 { $TaskStr = "SE_ADT_OBJECTACCESS_REGISTRY"; }
        else if $TaskValue == 12802 { $TaskStr = "SE_ADT_OBJECTACCESS_KERNEL"; }
        else if $TaskValue == 12803 { $TaskStr = "SE_ADT_OBJECTACCESS_SAM"; }
        else if $TaskValue == 12804 { $TaskStr = "SE_ADT_OBJECTACCESS_OTHER"; }
        else if $TaskValue == 12805 { $TaskStr = "SE_ADT_OBJECTACCESS_CERTIFICATIONAUTHORITY"; }
        else if $TaskValue == 12806 { $TaskStr = "SE_ADT_OBJECTACCESS_APPLICATIONGENERATED"; }
        else if $TaskValue == 12807 { $TaskStr = "SE_ADT_OBJECTACCESS_HANDLE"; }
        else if $TaskValue == 12808 { $TaskStr = "SE_ADT_OBJECTACCESS_SHARE"; }
        else if $TaskValue == 12809 { $TaskStr = "SE_ADT_OBJECTACCESS_FIREWALLPACKETDROPS"; }
        else if $TaskValue == 12810 { $TaskStr = "SE_ADT_OBJECTACCESS_FIREWALLCONNECTION"; }
        else if $TaskValue == 12811 { $TaskStr = "SE_ADT_OBJECTACCESS_DETAILEDFILESHARE"; }
        else if $TaskValue == 12812 { $TaskStr = "SE_ADT_OBJECTACCESS_REMOVABLESTORAGE"; }
        else if $TaskValue == 12813 { $TaskStr = "SE_ADT_OBJECTACCESS_CBACSTAGING"; }
        else if $TaskValue == 13056 { $TaskStr = "SE_ADT_PRIVILEGEUSE_SENSITIVE"; }
        else if $TaskValue == 13057 { $TaskStr = "SE_ADT_PRIVILEGEUSE_NONSENSITIVE"; }
        else if $TaskValue == 13058 { $TaskStr = "SE_ADT_PRIVILEGEUSE_OTHERS"; }
        else if $TaskValue == 13312 { $TaskStr = "SE_ADT_DETAILEDTRACKING_PROCESSCREATION"; }
        else if $TaskValue == 13313 { $TaskStr = "SE_ADT_DETAILEDTRACKING_PROCESSTERMINATION"; }
        else if $TaskValue == 13314 { $TaskStr = "SE_ADT_DETAILEDTRACKING_DPAPIACTIVITY"; }
        else if $TaskValue == 13315 { $TaskStr = "SE_ADT_DETAILEDTRACKING_RPCCALL"; }
        else if $TaskValue == 13316 { $TaskStr = "SE_ADT_DETAILEDTRACKING_PNPACTIVITY"; }
        else if $TaskValue == 13317 { $TaskStr = "SE_ADT_DETAILEDTRACKING_TOKENRIGHTADJ"; }
        else if $TaskValue == 13568 { $TaskStr = "SE_ADT_POLICYCHANGE_AUDITPOLICY"; }
        else if $TaskValue == 13569 { $TaskStr = "SE_ADT_POLICYCHANGE_AUTHENTICATIONPOLICY"; }
        else if $TaskValue == 13570 { $TaskStr = "SE_ADT_POLICYCHANGE_AUTHORIZATIONPOLICY"; }
        else if $TaskValue == 13571 { $TaskStr = "SE_ADT_POLICYCHANGE_MPSSCVRULEPOLICY"; }
        else if $TaskValue == 13572 { $TaskStr = "SE_ADT_POLICYCHANGE_WFPIPSECPOLICY"; }
        else if $TaskValue == 13573 { $TaskStr = "SE_ADT_POLICYCHANGE_OTHERS"; }
        else if $TaskValue == 13824 { $TaskStr = "SE_ADT_ACCOUNTMANAGEMENT_USERACCOUNT"; }
        else if $TaskValue == 13825 { $TaskStr = "SE_ADT_ACCOUNTMANAGEMENT_COMPUTERACCOUNT"; }
        else if $TaskValue == 13826 { $TaskStr = "SE_ADT_ACCOUNTMANAGEMENT_SECURITYGROUP"; }
        else if $TaskValue == 13827 { $TaskStr = "SE_ADT_ACCOUNTMANAGEMENT_DISTRIBUTIONGROUP"; }
        else if $TaskValue == 13828 { $TaskStr = "SE_ADT_ACCOUNTMANAGEMENT_APPLICATIONGROUP"; }
        else if $TaskValue == 13829 { $TaskStr = "SE_ADT_ACCOUNTMANAGEMENT_OTHERS"; }
        else if $TaskValue == 14080 { $TaskStr = "SE_ADT_DSACCESS_DSACCESS"; }
        else if $TaskValue == 14081 { $TaskStr = "SE_ADT_DSACCESS_DSCHANGES"; }
        else if $TaskValue == 14082 { $TaskStr = "SE_ADT_DS_REPLICATION"; }
        else if $TaskValue == 14083 { $TaskStr = "SE_ADT_DS_DETAILED_REPLICATION"; }
        else if $TaskValue == 14336 { $TaskStr = "SE_ADT_ACCOUNTLOGON_CREDENTIALVALIDATION"; }
        else if $TaskValue == 14337 { $TaskStr = "SE_ADT_ACCOUNTLOGON_KERBEROS"; }
        else if $TaskValue == 14338 { $TaskStr = "SE_ADT_ACCOUNTLOGON_OTHERS"; }
        else if $TaskValue == 14339 { $TaskStr = "SE_ADT_ACCOUNTLOGON_KERBCREDENTIALVALIDATION"; }
        else if $TaskValue == 65280 { $TaskStr = "SE_ADT_UNKNOWN_SUBCATEGORY"; }
        else { $TaskStr = "Unknown[" + $taskValue + "]"; }

    if $KeywordsStr == undef {
        if $TaskValue == 0 {
            $KeywordsStr = 'None';
        } else {
            $KeywordsStr = '0';
        }
    }

    if $TaskStr == undef {
        $TaskStr = $TaskValue;
    }

    if $EventType == 'AUDIT_SUCCESS' {
        $KeywordsStr = "Audit Success";
        $EventTypeNum = 8;
    } else {
        $KeywordsStr = "Audit Failure";
        $EventTypeNum = 16;
    }

        $Message = "AgentDevice=WindowsLog" +
            "\tAgentLogFile=" + $Channel +
            "\tSource=" + $SourceName +
            "\tComputer=" + hostname_fqdn() +
            "\tOriginatingComputer=" + host_ip() +
            "\tUser=" + $AccountName +
            "\tDomain=" + $Domain +
            "\tEventIDCode=" + $EventID +
            "\tEventType=" + $EventTypeNum +
            "\tEventCategory=" + $TaskValue +
            "\tRecordNumber=" + $RecordNumber +
            "\tTimeGenerated=" + $EpochTime +
            "\tTimeWritten=" + $EpochTime +
            "\tLevel=" + $EventTypeStr +
            "\tKeywords=" + $KeywordsStr +
            "\tTask=" + $TaskStr +
            "\tOpcode=" + $Opcode +
            "\tMessage=" + $Message;
        $Hostname = host_ip();
        delete($SourceName);
        delete($Severity);
        delete($SeverityValue);
        to_syslog_bsd();
    </Exec>
</Input>
Output sample
<13>Jul 15 20:24:43 10.80.1.49 AgentDevice=WindowsLog	AgentLogFile=System	Source=Service Control Manager	Computer=QRW.nxlog.org	OriginatingComputer=10.80.1.49	User=	Domain=	EventIDCode=7036	EventType=4	EventCategory=0	RecordNumber=9830	TimeGenerated=2019-07-15T20:24:43.296533Z	TimeWritten=2019-07-15T20:24:43.296533Z	Level=Informational	Keywords=9259400833873739776	Task=None	Opcode=Info	Message=The WinCollect service entered the stopped state.

Event Tracing for Windows (ETW)

To send Event Tracing for Windows logs to QRadar, use the im_etw module and convert the events to a tab-delimited key-value pair format supported by the corresponding QRadar DSM. Logs can be collected from different ETW channels and the configuration requirements depend on the log source. The examples below demonstrate how to collect Microsoft DHCP Server, Microsoft DNS Server, and Microsoft IIS logs.

If QRadar does not auto-discover the log source, add one manually. The Log Source Type should be set to Microsoft Windows Security Event Log and the Protocol Configuration should be set to Syslog—see Adding a QRadar log source.

For more information, see the QRadar DSM Guide on Microsoft Windows Security Event Log.

Microsoft DHCP Server logs

To collect DHCP Server logs, ensure that the DHCP-Server channels are enabled in Event Viewer. See DHCP server logs in Windows Event Log for instructions. The Analytics and Admin channels should be enabled.

Example 8. Sending DHCP logs to QRadar
nxlog.conf
<Extension syslog>
    Module      xm_syslog
</Extension>

<Input dhcp>
    Module      im_etw
    Provider    Microsoft-Windows-DHCP-Server
    <Exec>
        if $Category == undef $Category = 0;
        if $EventType == 'CRITICAL'
        {
            $EventTypeNum = 1;
            $EventTypeStr = "Critical";
        }
        else if $EventType == 'ERROR'
        {
            $EventTypeNum = 2;
            $EventTypeStr = "Error";
        }
        else if $EventType == 'INFO'
        {
            $EventTypeNum = 4;
            $EventTypeStr = "Informational";
        }
        else if $EventType == 'WARNING'
        {
            $EventTypeNum = 3;
            $EventTypeStr = "Warning";
        }
        else if $EventType == 'VERBOSE'
        {
            $EventTypeNum = 5;
            $EventTypeStr = "Verbose";
        }
        else
        {
            $EventTypeNum = 0;
            $EventTypeStr = "Audit";
        }

        if $OpcodeValue == 0 $Opcode = "Info";
        $EpochTime = string(integer($EventTime));
        $EpochTime =~ /^(?<sec>\d+)(?<ms>\d{6})$/;
        $EpochTime = $sec;

        # Events for Windows DHCP Server Operational Channel
        if $EventID == 70  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Configured by " + $ClientName + ".";
        } else if $EventID == 71  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Modified by " + $ClientName + ".";
        } else if $EventID == 72  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Deleted by " + $ClientName + ".";
        } else if $EventID == 73  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Activated by " + $ClientName + ".";
        } else if $EventID == 74  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is DeActivated by " + $ClientName + ".";
        } else if $EventID == 75  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Updated with Lease Duration: " + $ModifiedDuration +
            " seconds by " + $ClientName +
            ". The previous configured Lease Duration was: " +
            $OriginalDuration + " seconds.";
        } else if $EventID == 76  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Updated with Option Settings: " + $OptionName +
            " by " + $ClientName;
        } else if $EventID == 77  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Enabled for DNS Dynamic updates by " +
            $ClientName + ".";
        } else if $EventID == 78  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Disabled for DNS Dynamic updates by " +
            $ClientName + ".";
        } else if $EventID == 79  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Updated with DNS Settings by " + $ClientName +
            ": to dynamically update DNS A and PTR records on request by
            the DHCP Clients .";
        } else if $EventID == 80  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Updated with DNS Settings by " + $ClientName +
            ": to always dynamically update DNS A and PTR records.";
        } else if $EventID == 81  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Enabled for DNS Settings by " + $ClientName +
            ": to discard DNS A and PTR records when lease is deleted.";
        } else if $EventID == 82  {
            $DHCPMessage = "Scope: " + $IP_ScopeName + \
            " for IPv4 is Disabled for DNS Settings by " + $ClientName +
            ": to discard DNS A and PTR records when lease is deleted.";
        } else if $EventID == 83  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Enabled for DNS Settings by " + $ClientName +
            ": to dynamically update DNS A and PTR records for DHCP Clients" +
            " that do not request updates.";
        } else if $EventID == 84  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Disabled for DNS Settings by " + $ClientName +
            ": to dynamically update DNS A and PTR records for DHCP Clients" +
            " that do not request updates.";
        } else if $EventID == 85  {
            $DHCPMessage = "Policy based assignment has been disabled for " +
            "scope " + $IP_ScopeName + ".";
        } else if $EventID == 86  {
            $DHCPMessage = "Policy based assignment has been enabled for " +
            "scope " + $IP_ScopeName + ".";
        } else if $EventID == 87  {
            $DHCPMessage = "Name Protection setting is Enabled on Scope: " +
            $IP_Name + " for IPv4 by " + $ClientName + ".";
        } else if $EventID == 88  {
            $DHCPMessage = "Name Protection setting is Disabled on Scope: " +
            $IP_Name + " for IPv4 by " + $ClientName + ".";
        } else if $EventID == 89  {
            $DHCPMessage = "Scope: " + $IP_Name +
            " for IPv4 is Updated with support type: " + $ModifiedSupportType +
            " by " + $ClientName + ". The previous configured state was: " +
            $OriginalSupportType + ".";
        } else if $EventID == 90  {
            $DHCPMessage = "NAP Enforcement is Enabled on Scope: " +
            $IP_ScopeName + " for IPv4 by " + $ClientName + ".";
        } else if $EventID == 91  {
            $DHCPMessage = "NAP Enforcement is Disabled on Scope: " +
            $IP_ScopeName + " for IPv4 by " + $ClientName + ".";
        } else if $EventID == 92  {
            $DHCPMessage = "NAP Profile is configured on Scope: " +
            $IP_ScopeName + "  for IPv4 with the following NAP Profile: " +
            $NAP_ProfileName + " by " + $ClientName + ".";
        } else if $EventID == 93  {
            $DHCPMessage = "NAP Profile is Updated on Scope: " +
            $IP_ScopeName + " for IPv4 with the following NAP Profile: " +
            $NAP_ModifiedProfileName + " by " + $ClientName +
            ". The previous configured NAP Profile was: " +
            $NAP_OriginalProfileName + ".";
        } else if $EventID == 94  {
            $DHCPMessage = "The following NAP Profile: " + $IP_ScopeName +
            " is deleted on Scope: " + $NAP_ProfileName + " by " +
            $ClientName + ".";
        } else if $EventID == 95  {
            $DHCPMessage = "Scope: " + $IP_MulticastScopeName +
            " for Multicast IPv4 is Configured by " + $ClientName + ".";
        } else if $EventID == 96  {
            $DHCPMessage = "Scope: " + $IP_MulticastScopeName +
            " for Multicast IPv4 is Deleted by " + $ClientName + ".";
        } else if $EventID == 97  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Added in Superscope: " + $IP_SuperScopeName +
            " by " + $ClientName + ".";
        } else if $EventID == 98  {
            $DHCPMessage = "SuperScope: " + $IP_MulticastScopeName +
            " for IPv4 is Configured by " + $ClientName + ".";
        } else if $EventID == 99  {
            $DHCPMessage = "SuperScope: " + $IP_MulticastScopeName +
            " for IPv4 is Deleted by " + $ClientName + ".";
        } else if $EventID == 100  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " within SuperScope: " + $IP_SuperScopeName +
            " for IPv4 is Activated by " + $ClientName + ".";
        } else if $EventID == 101  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " within SuperScope: " + $IP_SuperScopeName +
            " for IPv4 is DeActivated by " + $ClientName + ".";
        } else if $EventID == 102  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Removed in Superscope: " + $IP_SuperScopeName +
            " by " + $ClientName +
            ". However, the Scope exists outside the Superscope.";
        } else if $EventID == 103  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Deleted in Superscope: " + $IP_SuperScopeName +
            " as well as Deleted permanently by " + $ClientName + ".";
        } else if $EventID == 104  {
            $DHCPMessage = "Delay Time: " + $UpdatedVal +
            " milliseconds for the OFFER message sent by Secondary Servers" +
            " is Updated on Scope: " + $IP_Name + " for IPv4 by " +
            $ClientName + ". The previous configured Delay Time was: " +
            $OriginalVal + " milliseconds.";
        } else if $EventID == 105  {
            $DHCPMessage = "Server level option " + $OptionName +
            " for IPv4 has been updated by " + $ClientName + ".";
        } else if $EventID == 106  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 is Configured under Scope " + $IP_Name + " by " +
            $ClientName + ".";
        } else if $EventID == 107  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 is Deleted under Scope " + $IP_Name + " by " +
            $ClientName + ".";
        } else if $EventID == 108  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Enabled for DNS Dynamic updates by " + $ClientName + ".";
        } else if $EventID == 109  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name + " is Disabled for" +
            " DNS Dynamic updates by " + $ClientName + ".";
        } else if $EventID == 110  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Updated with DNS Settings by " + $ClientName +
            ": to dynamically update DNS A and PTR records on request by" +
            " the DHCP Clients.";
        } else if $EventID == 111  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Updated with DNS Settings by " + $ClientName +
            ": to always dynamically update DNS A and PTR records.";
        } else if $EventID == 112  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Enabled for DNS Settings by " + $ClientName +
            ": to discard DNS A and PTR records when lease is deleted.";
        } else if $EventID == 113  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Disabled for DNS Settings by " + $ClientName +
            ": to discard DNS A and PTR records when lease is deleted.";
        } else if $EventID == 114  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Enabled for DNS Settings by " + $ClientName +
            ": to dynamically update DNS A and PTR records for DHCP Clients" +
            " that do not request updates.";
        } else if $EventID == 115  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Disabled for DNS Settings by " + $ClientName +
            ": to dynamically update DNS A and PTR records for DHCP Clients" +
            " that do not request updates.";
        } else if $EventID == 116  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv4 under Scope: " + $IP_Name +
            " is Updated with Option Setting: " + $OptionName +
            " by " + $ClientName + ".";
        } else if $EventID == 117  {
            $DHCPMessage = "Policy based assignment has been disabled" +
            " at server level.";
        } else if $EventID == 118  {
            $DHCPMessage = "Policy based assignment has been enabled" +
            " at server level.";
        } else if $EventID == 119  {
            $DHCPMessage = "Added exclusion IP Address range " +
            $ExclusionRange + " in the Address Pool for IPv4 under Scope: " +
            $IP_Name + " by " + $ClientName + ".";
        } else if $EventID == 120  {
            $DHCPMessage = "Deleted exclusion IP Address range " +
            $ExclusionRange + " in the Address Pool for IPv4 under Scope: " +
            $IP_Name + " by " + $ClientName + ".";
        } else if $EventID == 121  {
            $DHCPMessage = "Link Layer based filtering is Enabled in the" +
            " Allow List of the IPv4 by " + $ClientName + " ";
        } else if $EventID == 122  {
            $DHCPMessage = "Link Layer based filtering is Disabled in the" +
            " Allow List of the IPv4 by " + $ClientName + " ";
        } else if $EventID == 123  {
            $DHCPMessage = "Filter for physical address: " +
            $PhysicalAddress + ", hardware type: " + $HWType +
            " added to the IPv4 Allow List by " + $ClientName + ". ";
        } else if $EventID == 124  {
            $DHCPMessage = "Filter for physical address: " +
            $PhysicalAddress + ", hardware type: " + $HWType +
            " removed from the IPv4 Allow List by " + $ClientName + ". ";
        } else if $EventID == 125  {
            $DHCPMessage = "Link Layer based filtering is Enabled" +
            " in the Deny List of the IPv4 by " + $ClientName + " ";
        } else if $EventID == 126  {
            $DHCPMessage = "Link Layer based filtering is Disabled" +
            " in the Deny List of the IPv4 by " + $ClientName + " ";
        } else if $EventID == 127  {
            $DHCPMessage = "Filter for physical address: " +
            $PhysicalAddress + ", hardware type: " + $HWType +
            " added to the IPv4 Deny List by " + $ClientName + ". ";
        } else if $EventID == 128  {
            $DHCPMessage = "Filter for physical address: " +
            $PhysicalAddress + ", hardware type: " + $HWType +
            " removed from the IPv4 Deny List by " + $ClientName + ". ";
        } else if $EventID == 129  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Configured by " + $ClientName + ".";
        } else if $EventID == 130  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Deleted by " + $ClientName + ".";
        } else if $EventID == 131  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Activated by " + $ClientName + ".";
        } else if $EventID == 132  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is DeActivated by " + $ClientName + ".";
        } else if $EventID == 133  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Updated with Lease Preferred Lifetime:  " +
            $ModifiedDuration + " by " + $ClientName +
            ". The previous configured Lease Preferred Lifetime was: " +
            $OriginalDuration + ".";
        } else if $EventID == 134  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Updated with Lease Valid Lifetime: " +
            $ModifiedDuration + " by " + $ClientName +
            ". The previous configured Lease Valid Lifetime was: " +
            $OriginalDuration + ".";
        } else if $EventID == 135  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Updated with Option Setting: " + $OptionName +
            " by " + $ClientName + ".";
        } else if $EventID == 136  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Enabled for DNS Dynamic updates by " +
            $ClientName + ".";
        } else if $EventID == 137  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Disabled for DNS Dynamic updates by " +
            $ClientName + ".";
        } else if $EventID == 138  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Updated with DNS Settings by " + $ClientName +
            ": to dynamically update DNS AAAA and PTR records on request" +
            " by the DHCP Clients.";
        } else if $EventID == 139  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Updated with DNS Settings by " + $ClientName +
            ": to always dynamically update DNS AAAA and PTR records.";
        } else if $EventID == 140  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Enabled for DNS Settings by " + $ClientName +
            ": to discard DNS AAAA and PTR records when lease is deleted.";
        } else if $EventID == 141  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Disabled for DNS Settings by " + $ClientName +
            ": to discard DNS AAAA and PTR records when lease is deleted.";
        } else if $EventID == 142  {
            $DHCPMessage = "Name Protection setting is Enabled on Scope: " +
            $IP_Name + " for IPv6 by " + $ClientName + ".";
        } else if $EventID == 143  {
            $DHCPMessage = "Name Protection setting is Disabled on Scope: " +
            $IP_Name + " for IPv6 by " + $ClientName + ".";
        } else if $EventID == 145  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 is Configured under Scope " + $IP_Name + " by " +
            $ClientName + ".";
        } else if $EventID == 147  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 is Deleted under Scope " + $IP_Name + " by " +
            $ClientName + ".";
        } else if $EventID == 148  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 under Scope: " + $IP_Name +
            " is Enabled for DNS Dynamic updates by " + $ClientName + ".";
        } else if $EventID == 149  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 under Scope: " + $IP_Name + " is Disabled for" +
            " DNS Dynamic updates by " + $ClientName + ".";
        } else if $EventID == 150  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 under Scope: " + $IP_Name +
            " is Updated with DNS Settings by " + $ClientName +
            ": to dynamically update DNS AAAA and PTR records on request" +
            " by the DHCP Clients.";
        } else if $EventID == 151  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 under Scope: " + $IP_Name + \
            " is Updated with DNS Settings by " + $ClientName +
            ": to always dynamically update DNS AAAA and PTR records.";
        } else if $EventID == 152  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 under Scope: " + $IP_Name +
            " is Enabled for DNS Settings by " + $ClientName +
            ": to discard DNS AAAA and PTR records when lease is deleted.";
        } else if $EventID == 153  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 under Scope: " + $IP_Name +
            " is Disabled for DNS Settings by " + $ClientName +
            ": to discard DNS AAAA and PTR records when lease is deleted.";
        } else if $EventID == 154  {
            $DHCPMessage = "Reservation: " + $ReservationName +
            " for IPv6 under Scope: " + $IP_Name +
            " is Updated with Option Setting: " + $OptionName +
            " by " + $ClientName + ".";
        } else if $EventID == 155  {
            $DHCPMessage = "Added exclusion IP Address range " +
            $ExclusionRange + " in the Address Pool for IPv6 under Scope: " +
            $IP_Name + " by " + $ClientName + ".";
        } else if $EventID == 156  {
            $DHCPMessage = "Deleted exclusion IP Address range " +
            $ExclusionRange + " in the Address Pool for IPv6 under Scope: " +
            $IP_Name + " by " + $ClientName + ".";
        } else if $EventID == 157  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv6 is Modified by " + $ClientName + ".";
        } else if $EventID == 158  {
            $DHCPMessage = "DHCPv6 Stateless client inventory has been" +
            " enabled for the scope " + $IP_ScopeName + ".";
        } else if $EventID == 159  {
            $DHCPMessage = "DHCPv6 Stateless client inventory has been" +
            " disabled for the scope " + $IP_ScopeName + ".";
        } else if $EventID == 160  {
            $DHCPMessage = "DHCPv6 Stateless client inventory has been" +
            " enabled for the server.";
        } else if $EventID == 161  {
            $DHCPMessage = "DHCPv6 Stateless client inventory has been" +
            " disabled for the server.";
        } else if $EventID == 162  {
            $DHCPMessage = "Purge time interval for DHCPv6 stateless client" +
            " inventory for scope " + $IP_ScopeName + " has been set to " +
            $PurgeInterval + " hours.";
        } else if $EventID == 163  {
            $DHCPMessage = "Purge time interval for DHCPv6 stateless client" +
            " inventory for server has been set to " + $PurgeInterval +
            " hours.";
        } else if $EventID == 164  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Enabled" + " for DNS Settings by " + $ClientName +
            ": to disable dynamic updates for DNS PTR records.";
        } else if $EventID == 165  {
            $DHCPMessage = "Scope: " + $IP_ScopeName +
            " for IPv4 is Disabled for DNS Settings by " + $ClientName +
            ": to disable dynamic updates for DNS PTR records.";
        } else if $EventID == 166  {
            $DHCPMessage = "Server level option " + $OptionName +
            " for IPv6 has been updated by " + $ClientName + ".";
        } else if $EventID == 20220  {
            $DHCPMessage = "Policy " + $PolicyName +
            " for server is " + $String1 + ".";
        } else if $EventID == 20221  {
            $DHCPMessage = "Policy " + $PolicyName + " for scope " +
            $IP_ScopeName + " is " + $String1 + ".";
        } else if $EventID == 20222  {
            $DHCPMessage = "The conditions for server policy " +
            $PolicyName + " have been set to " + $String1 +
            ". The conditions are grouped by logical operator " +
            $String2 + ".";
        } else if $EventID == 20223  {
            $DHCPMessage = "The conditions for scope " + $IP_ScopeName +
            " policy " + $PolicyName + " have been set to " + $String1 +
            ". The conditions are grouped by logical operator " +
            $String2 + ".";
        } else if $EventID == 20224  {
            $DHCPMessage = "A new server wide IPv4 policy " + $PolicyName +
            " was created. The processing order of the policy is " +
            $ProcessingOrder + ".";
        } else if $EventID == 20225  {
            $DHCPMessage = "A new scope policy " + $PolicyName +
            " was created in scope " + $IP_ScopeName +
            ". The processing order of the policy is " + $ProcessingOrder + ".";
        } else if $EventID == 20226  {
            $DHCPMessage = "Policy " + $PolicyName +
            " was deleted from server.";
        } else if $EventID == 20227  {
            $DHCPMessage = "Policy " + $PolicyName +
            " was deleted from scope " + $IP_ScopeName + ".";
        } else if $EventID == 20228  {
            $DHCPMessage = "The IP address range from " + $String1 +
            " was set for the scope " + $IP_ScopeName + " policy " +
            $PolicyName + ".";
        } else if $EventID == 20229  {
            $DHCPMessage = "The IP address range from " + $String1 +
            " was removed from the scope " + $IP_ScopeName + " policy " +
            $PolicyName + ".";
        } else if $EventID == 20230  {
            $DHCPMessage = "The value " + $OptionValue +
            " was set for the option " + $OptionName +
            " for the server policy " + $PolicyName + ".";
        } else if $EventID == 20231  {
            $DHCPMessage = "The value " + $OptionValue + \
            " was set for the option " + $OptionName + " for the scope " +
            $IP_ScopeName + " policy " + $PolicyName + ".";
        } else if $EventID == 20232  {
            $DHCPMessage = "The value " + $OptionValue +
            " was removed from the option " + $OptionName +
            " for the server policy " + $PolicyName + ".";
        } else if $EventID == 20233  {
            $DHCPMessage = "The value " + $OptionValue +
            " was removed from the option " + $OptionName +
            " for the scope " + $IP_ScopeName + " policy " + $PolicyName + ".";
        } else if $EventID == 20234  {
            $DHCPMessage = "Server policy " + $PolicyName +
            " has been renamed to " + $String1 + ".";
        } else if $EventID == 20235  {
            $DHCPMessage = "Scope " + $IP_ScopeName + " policy " +
            $PolicyName + " has been renamed to " + $String1 + ".";
        } else if $EventID == 20236  {
            $DHCPMessage = "Description of server policy " + $PolicyName +
            " was set to " + $String1 + ".";
        } else if $EventID == 20237  {
            $DHCPMessage = "Description of scope " + $IP_ScopeName +
            " policy " + $PolicyName + " was set to " + $String1 + ".";
        } else if $EventID == 20238  {
            $DHCPMessage = "Processing order of server policy " +
            $PolicyName + " was changed to " + $Integer1 + " from " +
            $Integer2 + ".";
        } else if $EventID == 20239  {
            $DHCPMessage = "Processing order of scope " + $IP_ScopeName +
            " policy " + $PolicyName + " was changed to " + $Integer1 +
            " from " + $Integer2 + ".";
        } else if $EventID == 20240  {
            $DHCPMessage = "A failover relationship has been created" +
            " between servers " + $Server1Name + " and " + $Server2Name +
            " with the following configuration parameters: name: " +
            $RelationshipName + ", mode: load balance, maximum client" +
            " lead time: " + $Mclt + " seconds, load balance percentage ";
        } else if $EventID == 20241  {
            $DHCPMessage = "A failover relationship has been created " +
            " between servers " + $Server1Name + " and " + $Server2Name +
            " with the following configuration parameters: name: " +
            $RelationshipName + ", mode: hot standby, maximum client" +
            " lead time: " + $Mclt + " seconds, reserve address ";
        } else if $EventID == 20242  {
            $DHCPMessage = "Failover relationship " + $RelationshipName +
            " between " + $Server1Name + " and " + $Server2Name +
            " has been deleted.";
        } else if $EventID == 20243  {
            $DHCPMessage = "Scope " + $ScopeAddress +
            " has been added to the failover relationship " +
            $RelationshipName + " with server " + $Server2Name + ".";
        } else if $EventID == 20244  {
            $DHCPMessage = "Scope " + $ScopeAddress +
            " has been removed from the failover relationship " +
            $RelationshipName + " with server " + $Server2Name + ".";
        } else if $EventID == 20245  {
            $DHCPMessage = "The failover configuration parameter MCLT" +
            " for failover relationship " + $RelationshipName +
            " with server " + $Server2Name + " has been changed from " +
            $OldValue + " seconds to " + $NewValue + " seconds.";
        } else if $EventID == 20246  {
            $DHCPMessage = "The failover configuration parameter auto" +
            " switch over interval for failover relationship " +
            $RelationshipName + " with server " + $Server2Name +
            " has been changed from " + $OldValue + " seconds to " +
            $NewValue + " seconds.";
        } else if $EventID == 20247  {
            $DHCPMessage = "The failover configuration parameter reserve" +
            " address percentage for failover relationship " +
            $RelationshipName + " with server " + $Server2Name +
            " has been changed from " + $OldValue + " to " + $NewValue + ".";
        } else if $EventID == 20248  {
            $DHCPMessage = "The failover configuration parameter load" +
            " balance percentage for failover relationship " +
            $RelationshipName + " with server " + $Server2Name +
            " has been changed from " + $OldValue + " to " + $NewValue +
            " on this server.";
        } else if $EventID == 20249  {
            $DHCPMessage = "The failover configuration parameter mode" +
            " for failover relationship " + $RelationshipName +
            " with server " + $Server2Name +
            " has been changed from hot standby to load balance.";
        } else if $EventID == 20250  {
            $DHCPMessage = "The failover configuration parameter mode" +
            " for failover relationship " + $RelationshipName +
            " with server " + $Server2Name +
            " has been changed from load balance to hot standby.";
        } else if $EventID == 20311  {
            $DHCPMessage = "The shared secret for failover relationship " +
            $Server2Name + " with server " + $RelationshipName +
            " has been changed.";
        } else if $EventID == 20312  {
            $DHCPMessage = "Message authentication for failover" +
            " relationship " + $Server2Name + " with server " +
            $RelationshipName + " has been enabled.";
        } else if $EventID == 20313  {
            $DHCPMessage = "Message authentication for failover" +
            " relationship " + $Server2Name + " with server " +
            $RelationshipName + " has been disabled.";
        } else if $EventID == 20315  {
            $DHCPMessage = "DNSSuffix of scope " + $IP_ScopeName +
            " policy " + $PolicyName + " was set to " + $String1 + ".";
        } else if $EventID == 20316  {
            $DHCPMessage = "DNSSuffix of server policy " + $PolicyName +
            " was set to " + $String1 + ".";
        } else {
            $DHCPMessage = "Unknown event not part of the Windows DHCP" + 
            " Server Operational Channel.";
        }
        if $Task == undef $Task = "None";
        $Message = "AgentDevice=WindowsLog" +
            "\tAgentLogFile=Microsoft-Windows-Dhcp-Server/Operational" +
            "\tPluginVersion=7.3.1.16" +
            "\tSource=" + $SourceName +
            "\tComputer=" + hostname_fqdn() +
            "\tOriginatingComputer=" + host_ip() +
            "\tUser=" + $AccountName +
            "\tDomain=" + $Domain +
            "\tEventID=" + $EventID +
            "\tEventIDCode=" + $EventID +
            "\tEventType=" + $EventTypeNum +
            "\tRecordNumber=" + $RecordNumber +
            "\tTimeGenerated=" + $EpochTime +
            "\tTimeWritten=" + $EpochTime +
            "\tLevel=" + $EventTypeStr +
            "\tKeywords=" + $Keywords +
            "\tTask=" + $Task +
            "\tOpcode=" + $Opcode +
            "\tMessage=" + $DHCPMessage;
        to_syslog_bsd();
    </Exec>
</Input>
Output sample
<14>Aug 13 05:30:01 WINSRV-DHCP Microsoft-Windows-DHCP-Server[4672]: AgentDevice=WindowsLog	AgentLogFile=Microsoft-Windows-Dhcp-Server/Operational	PluginVersion=7.3.1.16	Source=Microsoft-Windows-DHCP-Server	Computer=WINSRV-DHCP.example.com	OriginatingComputer=192.168.0.100	User=Administrator	Domain=EXAMPLE	EventID=20224	EventIDCode=20224	EventType=4	RecordNumber=	TimeGenerated=1628850601	TimeWritten=1628850601	Level=Informational	Keywords=9223372036854775808	Task=None	Opcode=Info	Message=A new server wide IPv4 policy test 1 was created. The processing order of the policy is 6.

Microsoft DNS Server logs

DNS Server logs can be collected from the DNS-Server/Analytical channel. There are 23 event IDs that can be collected from this channel, providing essential information for analysis and correlation. See the complete list of Analytic events in the Microsoft documentation.

No additional packages need to be installed on the IBM Qradar appliance, however the Microsoft Windows Security Event Log DSM (DSM-MicrosoftWindows-7.x) must be available to parse Windows events. Additionally, processing needs to be done in the NXLog configuration to output events in a format that can be parsed by this DSM.

Since events from the Audit channel are not processed by IBM Qradar, the example configuration below only collects events from the Analytical channel.
Example 9. Sending DNS Server logs to QRadar
nxlog.conf
<Extension syslog>
    Module      xm_syslog
</Extension>

<Extension etw_qradar>
    Module      xm_rewrite
    <Exec>
        if $Category == undef $Category = 0;
        if $EventType == 'CRITICAL'
        {
            $EventTypeNum = 1;
            $EventTypeStr = "Critical";
        }
        else if $EventType == 'ERROR'
        {
            $EventTypeNum = 2;
            $EventTypeStr = "Error";
        }
        else if $EventType == 'INFO'
        {
            $EventTypeNum = 4;
            $EventTypeStr = "Informational";
        }
        else if $EventType == 'WARNING'
        {
            $EventTypeNum = 3;
            $EventTypeStr = "Warning";
        }
        else if $EventType == 'VERBOSE'
        {
            $EventTypeNum = 5;
            $EventTypeStr = "Verbose";
        }
        else
        {
            $EventTypeNum = 0;
            $EventTypeStr = "Audit";
        }

        if $OpcodeValue == 0 $Opcode = "Info";
        $EpochTime = string(integer($EventTime));
        $EpochTime =~ /^(?<sec>\d+)(?<ms>\d{6})$/;
        $EpochTime = $sec;

		    # The following list set writes the message as
        # specified by Microsoft for the Analytical Channel
        if $EventID == 256
        {
            $DNSMessage =
            "\tMessage=QUERY_RECEIVED: TCP=" + $TCP +
            "; Interface=" + $InterfaceIP +
            "; Source=" + $Source +
            "; RD=" + $RD +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; XID=" + $XID +
            "; Port=" + $Port +
            "; Flags" + $Flags +
            "; PacketData=" + $PacketData;
        } else if $EventID == 257 {
            $DNSMessage =
            "\tMessage=RESPONSE_SUCCESS: TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Destination=" + $Destination +
            "; AA=" + $AA +
            "; AD=" + $AD +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; XID=" + $XID +
            "; DNSSEC=" + $DNSSEC +
            "; RCODE=" + $RCODE +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; Scope=" + $Scope +
            "; Zone=" + $Zone +
            "; PolicyName=" + $PolicyName +
            "; PacketData=" + $PacketData;
        } else if $EventID == 258 {
            $DNSMessage =
            "\tMessage=REPONSE_FAILURE: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Reason=" + $Reason +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; XID=" + $XID +
            "; RCODE=" + $RCODE +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; Zone=" + $Zone +
            "; PolicyName=" + $PolicyName +
            "; PacketData=" + $PacketData;
        } else if $EventID == 259 {
            $DNSMessage =
            "\tMessage=IGNORED_QUERY: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Reason=" + $Reason +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; XID=" + $XID +
            "; Zone=" + $Zone +
            "; PolicyName=" + $PolicyName;
        } else if $EventID == 260 {
            $DNSMessage =
            "\tMessage=RECURSE_QUERY_OUT: " +
            "TCP=" + $TCP +
            "; Destination=" + $Destination +
            "; InterfaceIP=" + $InterfaceIP +
            "; RD=" + $RD +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; XID=" + $XID +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; ServerScope=" + $ServerScope +
            "; CacheScope=" + $CacheScope +
            "; PolicyName=" + $PolicyName +
            "; PacketData=" + $PacketData;
        } else if $EventID == 261 {
            $DNSMessage =
            "\tMessage=RECURSE_RESPONSE_IN: " +
            "TCP=" + $TCP +
            "; Source=" + $Source +
            "; InterfaceIP=" + $InterfaceIP +
            "; AA=" + $AA +
            "; AD=" + $AD +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; XID=" + $XID +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; ServerScope=" + $ServerScope +
            "; CacheScope=" + $CacheScope +
            "; PacketData=" + $PacketData;
        } else if $EventID == 262 {
            $DNSMessage =
            "\tMessage=RECURSE_QUERY_TIMEOUT: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; XID=" + $XID +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; ServerScope=" + $ServerScope +
            "; CacheScope=" + $CacheScope;
        } else if $EventID == 263 {
            $DNSMessage =
            "\tMessage=DYN_UPDATE_RECV: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Source=" + $Source +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; SECURE=" + $SECURE +
            "; PacketData=" + $PacketData;
        } else if $EventID == 264 {
            $DNSMessage =
            "\tMessage=DYN_UPDATE_RESPONSE: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; RCODE=" + $RCODE +
            "; PolicyName=" + $PolicyName +
            "; PacketData=" + $PacketData;
        } else if $EventID == 265 {
            $DNSMessage =
            "\tMessage=IXFR_REQ_OUT: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Source=" + $Source +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; PacketData=" + $PacketData;
        } else if $EventID == 266 {
            $DNSMessage =
            "\tMessage=IXFR_REQ_RECV: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Source=" + $Source +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; PacketData=" + $PacketData;
        } else if $EventID == 267 {
            $DNSMessage =
            "\tMessage=IXFR_RESP_OUT: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; RCODE=" + $RCODE +
            "; PacketData=" + $PacketData;
        } else if $EventID == 268 {
            $DNSMessage =
            "\tMessage=IXFR_RESP_RECV: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; RCODE=" + $RCODE +
            "; PacketData=" + $PacketData;
        } else if $EventID == 269 {
            $DNSMessage =
            "\tMessage=AXFR_REQ_OUT: " +
            "TC=" + $TC +
            "; Source=" + $Source +
            "; InterfaceIP=" + $InterfaceIP +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; PacketData=" + $PacketData;
        } else if $EventID == 270 {
            $DNSMessage =
            "\tMessage=AXFR_REQ_RECV: " +
            "TC=" + $TC +
            "; Source=" + $Source +
            "; InterfaceIP=" + $InterfaceIP +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; PacketData=" + $PacketData;
        } else if $EventID == 271 {
            $DNSMessage =
            "\tMessage=AXFR_RESP_OUT: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; RCODE=" + $RCODE;
        } else if $EventID == 272 {
            $DNSMessage =
            "\tMessage=AXFR_RESP_RECV: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; RCODE=" + $RCODE;
        } else if $EventID == 273 {
            $DNSMessage =
            "\tMessage=XFR_NOTIFY_RECV: " +
            "Source=" + $Source +
            "; InterfaceIP=" + $InterfaceIP +
            "; QNAME=" + $QNAME +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; PacketData=" + $PacketData;
        } else if $EventID == 274 {
            $DNSMessage =
            "\tMessage=XFR_NOTIFY_OUT: " +
            "Destination=" + $Destination +
            "; InterfaceIP=" + $InterfaceIP +
            "; QNAME=" + $QNAME +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; PacketData=" + $PacketData;
        } else if $EventID == 275 {
            $DNSMessage =
            "\tMessage=XFR_NOTIFY_ACK_IN: " +
            "Source=" + $Source +
            "; InterfaceIP=" + $InterfaceIP +
            "; PacketData=" + $PacketData;
        } else if $EventID == 276 {
            $DNSMessage =
            "\tMessage=XFR_NOTIFY_ACK_OUT: " +
            "Destination=" + $Destination +
            "; InterfaceIP=" + $InterfaceIP +
            "; Zone=" + $Zone +
            "; PacketData=" + $PacketData;
        } else if $EventID == 277 {
            $DNSMessage =
            "\tMessage=DYN_UPDATE_FORWARD: " +
            "TCP=" + $TCP +
            "; ForwardInterfaceIP=" + $ForwardInterfaceIP +
            "; Destination=" + $Destination +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; RCODE=" + $RCODE +
            "; PacketData=" + $PacketData;
        } else if $EventID == 278 {
            $DNSMessage =
            "\tMessage=DYN_UPDATE_RESPONSE_IN: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Source=" + $Source +
            "; QNAME=" + $QNAME +
            "; XID=" + $XID +
            "; ZoneScope=" + $ZoneScope +
            "; Zone=" + $Zone +
            "; RCODE=" + $RCODE +
            "; PacketData=" + $PacketData;
        } else if $EventID == 279 {
            $DNSMessage =
            "\tMessage=INTERNAL_LOOKUP_CNAME: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Source=" + $Source +
            "; RD=" + $RD +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; XID=" + $XID +
            "; PacketData=" + $PacketData;
        } else if $EventID == 280 {
            $DNSMessage =
            "\tMessage=INTERNAL_LOOKUP_ADDITIONAL: " +
            "TCP=" + $TCP +
            "; InterfaceIP=" + $InterfaceIP +
            "; Source=" + $Source +
            "; RD=" + $RD +
            "; QNAME=" + $QNAME +
            "; QTYPE=" + $QTYPE +
            "; Port=" + $Port +
            "; Flags=" + $Flags +
            "; XID=" + $XID +
            "; PacketData=" + $PacketData;
        } else {
            drop();
            log_info("Dropped Event");
        }

        $Message = "AgentDevice=WindowsLog" +
            "\tAgentLogFile=" + $SourceName + "/Analytical" +
            "\tPluginVersion=7.3.1.16" +
            "\tSource=" + $SourceName +
            "\tComputer=" + hostname_fqdn() +
            "\tOriginatingComputer=" + host_ip() +
            "\tUser=" + $AccountName +
            "\tDomain=" + $Domain +
            "\tEventID=" + $EventID +
            "\tEventIDCode=" + $EventID +
            "\tEventType=" + $EventTypeNum +
            "\tEventCategory=" + $EventTypeNum +
            "\tRecordNumber=" + $RecordNumber +
            "\tTimeGenerated=" + $EpochTime +
            "\tTimeWritten=" + $EpochTime +
            "\tLevel=" + $EventTypeStr +
            "\tKeywords=" + $Keywords +
            "\tTask=" + $Task +
            "\tOpcode=" + $OpcodeValue +
            $DNSMessage;
    </Exec>
    Delete      SourceName, Severity, SeverityValue
</Extension>

<Input dns>
    Module      im_etw
    Provider    Microsoft-Windows-DNSServer
    Exec        etw_qradar->process();
    Exec        to_syslog_bsd();
</Input>
Output sample
<11>Sep 14 10:19:22 WINSRV-DNS AgentDevice=WindowsLog	AgentLogFile=Microsoft-Windows-DNSServer/Analytical	PluginVersion=7.3.1.16	Source=Microsoft-Windows-DNSServer	Computer=WINSRV-DNS.example.com	OriginatingComputer=192.168.0.100	User=SYSTEM	Domain=NT AUTHORITY	EventID=258	EventIDCode=258	EventType=2	EventCategory=2	RecordNumber=	TimeGenerated=1631632762	TimeWritten=1631632762	Level=Error	Keywords=9223372036854775812	Task=	Opcode=0	Message=REPONSE_FAILURE: TCP=0; InterfaceIP=::1; Reason=System; Destination=::1; QNAME=go.microsoft.com.; QTYPE=1; XID=27369; RCODE=2; Port=62544; Flags=33154; Zone=..Cache; PolicyName=NULL; PacketData=0x6AE98182000100000000000002676F096D6963726F736F667403636F6D0000010001

Microsoft IIS logs

Microsoft IIS needs to be configured to output logs to ETW. See Configuring logging in the Microsoft IIS chapter for instructions. The Log Event Destination should be set to ETW event only.

To parse Microsoft IIS logs, the Microsoft Internet Information Services (IIS) Server DSM must be installed on the QRadar appliance. Look for DSM-MicrosofIIS-7.x under Admin > Auto Update.

Example 10. Sending IIS logs to QRadar
nxlog.conf
<Extension syslog>
    Module      xm_syslog
</Extension>

<Input iis>
    Module      im_etw
    Provider    Microsoft-Windows-IIS-Logging
    <Exec>
        if ${cs-uri-query} == undef ${cs-uri-query} = "-";
        if ${cs-username} == undef ${cs-username} = "-";
        if ${cs(Referer)} == undef ${cs(Referer)} = "-";
        $Message = "AgentDevice=MSIIS" +
            "\tAgentLogFile=Microsoft-Windows-IIS-Logging" +
            "\tAgentLogFormat=W3C" +
            "\tAgentLogProtocol=W3C" +
            "\tdate=" + $date +
            "\ttime=" + $time +
            "\ts-ip=" + ${s-ip} +
            "\tcs-method=" + ${cs-method} +
            "\tcs-uri-stem=" + ${cs-uri-stem} +
            "\tcs-uri-query=" + ${cs-uri-query} +
            "\ts-port=" + ${s-port} +
            "\tcs-username=" + ${cs-username} +
            "\tc-ip=" + ${c-ip} +
            "\tcs(User-Agent)=" + ${csUser-Agent} +
            "\tcs(Referer)=" + ${csReferer} +
            "\tsc-status=" + ${sc-status} +
            "\tsc-substatus=" + ${sc-substatus} +
            "\tsc-win32-status=" + ${sc-win32-status} +
            "\ttime-taken=" + ${time-taken};
        $EventTime = parsedate($date + " " + $time);
        $Hostname = host_ip();
        delete($SourceName);
        to_syslog_bsd();
    </Exec>
</Input>
Output sample
<14>Aug 13 21:27:46 192.168.88.220 AgentDevice=MSIIS	AgentLogFile=Microsoft-Windows-IIS-Logging	AgentLogFormat=W3C	AgentLogProtocol=W3C	date=2021-08-13	time=21:27:46	s-ip=192.168.88.220	cs-method=GET	cs-uri-stem=/favicon.ico	cs-uri-query=-	s-port=80	cs-username=-	c-ip=192.168.88.218	cs(User-Agent)=Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64;+rv:91.0)+Gecko/20100101+Firefox/91.0	cs(Referer)=http://192.168.88.220/	sc-status=404	sc-substatus=0	sc-win32-status=2	time-taken=77

Forwarding logs

Use an output instance to forward the processed logs to QRadar SIEM. The configurations shown here can be used with any of the above input instances. Because all event formatting is done in the input instances above, the output instances here do not require any Exec directives (the $raw_event field is passed without any further modification).

Example 11. Forwarding logs via TCP

This om_tcp instance sends logs to QRadar via TCP. In this example, events are sent from the Microsoft IIS and Windows Event Log sources.

nxlog.conf
<Output qradar>
    Module  om_tcp
    Host    10.0.0.2
    Port    514
</Output>

<Route r>
    Path    iis, eventlog => qradar
</Route>

Forwarding logs with TLS requires adding a TLS Syslog listener, as described in Adding a TLS Syslog log source above. The root certificate authority (CA) certificate, which is used to verify the authenticity of the QRadar receiver’s certificate, should be provided to om_ssl with either CADir or CAFile.

Example 12. Forwarding logs with TLS

In this example, the om_ssl module is used to send logs to QRadar securely, with TLS encryption.

nxlog.conf
<Output qradar>
    Module  om_ssl
    Host    10.0.0.2
    Port    6514
    CAFile  C:\Program Files\cert\rootCA.pem
</Output>
Disclaimer

While we endeavor to keep the information in this topic up to date and correct, NXLog makes no representations or warranties of any kind, express or implied about the completeness, accuracy, reliability, suitability, or availability of the content represented here. We update our screenshots and instructions on a best-effort basis.

The accurateness of the content was tested and proved to be working in our lab environment at the time of the last revision with the following software versions:

IBM QRadar CE 7.3.3
NXLog EE 5.3.6985

Last revision: 13 August 2020