Step 1: Setup Server
- Install a log aggregation server is out of scope of this document
Step 2: Setup Client
- Download and install NXLog Client:
- Latest edition: https://nxlog.co/downloads/nxlog-ce
- Automated install: choco install -y nxlog (version 2.10.2150 as of August 2021)
- Readme File content:
Please edit the configuration file after installation. This file is
located in the `conf` directory where NXLog was installed (default
`C:\Program Files (x86)\nxlog\conf\nxlog.conf` on 64-bit Windows). If
you chose a custom installation directory, you will need to update the
ROOT directory specified in the configuration file before the NXLog
service will start.
The NXLog service can be started from the Services console (run
`services.msc`) or will be started automatically at the next
boot. Alternatively, the service can be started by executing
`nxlog.exe`, located in the installation directory. The `-f` command
line argument can be used to run NXLog in the foreground.
By default, NXLog will write its own messages to the log file named
`nxlog.log` in the `data` directory (default `C:\Program Files
(x86)\nxlog\data\nxlog.log` on 64-bit Windows). If you have trouble
starting or running NXLog, check that file for errors.
See the NXLog Reference Manual for details about configuration and
usage. The Reference Manual is installed in the `doc` directory
(default `C:\Program Files (x86)\nxlog\doc` on 64-bit Windows) and
should also be available online at <https://nxlog.co/resources>.
- Configure:
- How to configure: https://nxlog.co/page/eventlog-to-syslog.html
- Edit the file at C:\Program Files (x86)\nxlog\conf\nxlog.conf
# Uncomment these line if using Graylog
#<Extension _gelf>
# Module xm_gelf
#</Extension>
# How to generate query: https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/advanced-xml-filtering-in-the-windows-event-viewer/ba-p/399761
# Please note that indentation is important!
<Input im_msvistalog>
Module im_msvistalog
Query <QueryList>\
<Query Id="0">\
# This is an example of Windows logon RDP mode 10
<Select Path="Security">*[System[(EventID=4624)]] and *[EventData[(Data=10)]]</Select>\
</Query>\
</QueryList>
</Input>
<Output om_udp>
Module om_udp
Host [IPADDRESSHERE]
Port 514
Exec to_syslog_snare(); # Use this if Graylog: OutputType GELF
</Output>
<Route out>
Path im_msvistalog => om_udp
</Route>
- Confirm whether remote host port is reachable from client
PS C:\Windows\system32> test-netconnection syslog-server -port 514
ComputerName : syslog-server
RemoteAddress : x.x.x.x
RemotePort : 514
InterfaceAlias : Ethernet 2
SourceAddress : x.x.x.x
PingSucceeded : True
PingReplyDetails (RTT) : 1 ms
TcpTestSucceeded : True
# Success
PS C:\Windows\system32> portqry -n syslog-server -p udp -e 514
Querying target system called:
syslog-server
Attempting to resolve name to IP address...
Name resolved to x.x.x.x
querying...
UDP port 514 (syslog service): LISTENING or FILTERED
# Success
PS C:\Windows\system32> portqry -n syslog-server -p udp -e 514
Querying target system called:
syslog-server
Attempting to resolve name to IP address...
Name resolved to x.x.x.x
querying...
--- some response data ---
UDP port 514 (syslog service): LISTENING
# Failure
PS C:\Windows\system32> portqry -n syslog-server -p udp -e 514
Querying target system called:
localhost
Attempting to resolve name to IP address...
Name resolved to x.x.x.x
querying...
UDP port 514 (syslog service): NOT LISTENING
- Start NXLog client service
PS C:\Windows\system32> start-service NXLog
- Troubleshooting
- Sample problem:
PS C:\Windows\system32> start-service nxlog
start-service : Service 'nxlog (nxlog)' cannot be started due to the following error: Cannot start service nxlog on
computer '.'.
At line:1 char:1
+ start-service nxlog
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Start-Service],
ServiceCommandException
+ FullyQualifiedErrorId : CouldNotStartService,Microsoft.PowerShell.Commands.StartServiceCommand
PS C:\Windows\system32> &"C:\Program Files (x86)\nxlog\nxlog.exe" -c "C:\Program Files (x86)\nxlog\conf\nxlog.conf"
Expected </Input> but saw </Query> at C:\Program Files (x86)\nxlog\conf\nxlog.conf:53
- Resolution to error message above is to fix the indentation of the config file
- Check service connections
PS C:\Windows\system32> netstat -nbt| select-string -Pattern "nxlog" -Context 2
[rstudio.exe]
TCP 127.0.0.1:61682 127.0.0.1:61683 ESTABLISHED
> [nxlog.exe]
TCP 127.0.0.1:61683 127.0.0.1:61682 ESTABLISHED
- Check server for established tcp connections
[thanos@syslog-server thanos] #
remoteIP=x.x.x.x
match=$null
while [ -z "$match" ]
do
clear
echo "Checking for incoming connection from $remoteIP"
match=$(netstat -na|grep $remoteIP)
[[ ! -z "$match" ]] && echo "$match" || sleep 1
done
- check which daemons & owners listen to which ports
[thanos@syslog-server thanos] # netstat -elpt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:sunrpc 0.0.0.0:* LISTEN root 7956 1/systemd
tcp 0 0 0.0.0.0:33427 0.0.0.0:* LISTEN root 13042 -
tcp 0 0 localhost:domain 0.0.0.0:* LISTEN systemd-resolve 8111 673/systemd-resolve
tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN root 12384 1162/sshd: /usr/sbi
tcp 0 0 localhost.localdom:smtp 0.0.0.0:* LISTEN root 9157 787/master
tcp 0 0 0.0.0.0:46463 0.0.0.0:* LISTEN rpcuser 12960 1275/rpc.statd
tcp 0 0 0.0.0.0:shell 0.0.0.0:* LISTEN root 11650 1252/rsyslogd
tcp 0 0 localhost.localdom:smux 0.0.0.0:* LISTEN root 9674 811/snmpd
- Check RDP logging activities
client=SYSLOGCLIENT
year=$(date +"%Y")
clientlog=/var/log/rsyslog/hosts/$client/$year/messages
rdpLogFilter=".*Source Port: \w+"
tail -f $clientlog | grep -oP $rdpLogFilter
cat $clientlog | grep -oP $rdpLogFilter
- Certain expected logging (such as logons and logoffs) not being sent to server
# on client Windows machine, turn on auditing of logon and logoff events
auditpol /set /category:"Logon/logoff" /failure:enable
auditpol /set /category:"Logon/logoff" /success:enable
# To persist settings for domain joined computers, it's necessary to create a GP with this configuration: Computer Configuration > Policies > Windows Settings > Security Settings > Advanced Audit Policy Configuration > Audit Policies > Logon/Logoff
Configuration Example 1:
Panic Soft
#NoFreeOnExit TRUE
define ROOT C:\Program Files (x86)\nxlog
define CERTDIR %ROOT%\cert
define CONFDIR %ROOT%\conf
define LOGDIR %ROOT%\data
define LOGFILE %LOGDIR%\nxlog.log
LogFile %LOGFILE%
Moduledir %ROOT%\modules
CacheDir %ROOT%\data
Pidfile %ROOT%\data\nxlog.pid
SpoolDir %ROOT%\data
<Extension _syslog>
Module xm_syslog
</Extension>
<Extension _charconv>
Module xm_charconv
AutodetectCharsets iso8859-2, utf-8, utf-16, utf-32
</Extension>
<Extension _exec>
Module xm_exec
</Extension>
<Extension _fileop>
Module xm_fileop
# Check the size of our log file hourly, rotate if larger than 5MB
<Schedule>
Every 1 hour
Exec if (file_exists('%LOGFILE%') and \
(file_size('%LOGFILE%') >= 5M)) \
file_cycle('%LOGFILE%', 8);
</Schedule>
# Rotate our log file every week on Sunday at midnight
<Schedule>
When @weekly
Exec if file_exists('%LOGFILE%') file_cycle('%LOGFILE%', 8);
</Schedule>
</Extension>
<Extension _gelf>
Module xm_gelf
</Extension>
# How to generate query: https://techcommunity.microsoft.com/t5/ask-the-directory-services-team/advanced-xml-filtering-in-the-windows-event-viewer/ba-p/399761
# Please note that indentation is important!
<Input from_eventlog>
Module im_msvistalog
<QueryXML>
<QueryList>
<Query Id="0">
<Select Path="Security">
*[System[Level=0 and (EventID=4624 or EventID=4647)]]
</Select>
</Query>
</QueryList>
</QueryXML>
</Input>
# Source: https://docs.nxlog.co/userguide/configure/forwarding-logs.html
<Output om_udp>
Module om_udp # OR om_tcp (depending on server listening port discovered in http://{graylog.server.url}/system/inputs)
Host 10.10.10.88
Port 12222
OutputType GELF_UDP # OR GELF_TCP OR Exec to_syslog_ietf(); OR to_syslog_snare(); OR Binary OR to_json();
</Output>
<Route out>
Path from_eventlog => out
</Route>
Configuration Example 2:
Panic Soft
#NoFreeOnExit TRUE
define ROOT C:\Program Files (x86)\nxlog
define CERTDIR %ROOT%\cert
define CONFDIR %ROOT%\conf
define LOGDIR %ROOT%\data
define LOGFILE %LOGDIR%\nxlog.log
LogFile %LOGFILE%
Moduledir %ROOT%\modules
CacheDir %ROOT%\data
Pidfile %ROOT%\data\nxlog.pid
SpoolDir %ROOT%\data
<Extension _syslog>
Module xm_syslog
</Extension>
<Extension _charconv>
Module xm_charconv
AutodetectCharsets iso8859-2, utf-8, utf-16, utf-32
</Extension>
<Extension _exec>
Module xm_exec
</Extension>
<Extension _fileop>
Module xm_fileop
# Check the size of our log file hourly, rotate if larger than 5MB
<Schedule>
Every 1 hour
Exec if (file_exists('%LOGFILE%') and \
(file_size('%LOGFILE%') >= 5M)) \
file_cycle('%LOGFILE%', 8);
</Schedule>
# Rotate our log file every week on Sunday at midnight
<Schedule>
When @weekly
Exec if file_exists('%LOGFILE%') file_cycle('%LOGFILE%', 8);
</Schedule>
</Extension>
<Extension _gelf>
Module xm_gelf
</Extension>
<Input im_msvistalog>
Module im_msvistalog
Query <QueryList>\
<Query Id="0">\
<Select Path="System">*[System[(Level=1 or Level=2 or Level=3)]]</Select>\
<Select Path="Application">*[System[(Level=1 or Level=2 or Level=3)]]</Select>\
<Select Path="Security">*[System[Level=0 and (EventID=4624 or EventID=4647)]]</Select>\
</Query>\
</QueryList>
</Input>
<Output send_graylog>
Module om_tcp
Host 10.10.10.88
Port 12201
OutputType GELF_TCP
</Output>
<Processor norepeat>
Module pm_norepeat
CheckFields Message
</Processor>
<Route out>
Path im_msvistalog => norepeat => send_graylog
</Route>
Example 3:
Panic Soft
#NoFreeOnExit TRUE
define ROOT C:\Program Files (x86)\nxlog
define CERTDIR %ROOT%\cert
define CONFDIR %ROOT%\conf
define LOGDIR %ROOT%\data
define LOGFILE %LOGDIR%\nxlog.log
LogFile %LOGFILE%
Moduledir %ROOT%\modules
CacheDir %ROOT%\data
Pidfile %ROOT%\data\nxlog.pid
SpoolDir %ROOT%\data
<Extension _syslog>
Module xm_syslog
</Extension>
<Extension _charconv>
Module xm_charconv
AutodetectCharsets iso8859-2, utf-8, utf-16, utf-32
</Extension>
<Extension _exec>
Module xm_exec
</Extension>
<Extension _fileop>
Module xm_fileop
# Check the size of our log file hourly, rotate if larger than 5MB
<Schedule>
Every 1 hour
Exec if (file_exists('%LOGFILE%') and \
(file_size('%LOGFILE%') >= 5M)) \
file_cycle('%LOGFILE%', 8);
</Schedule>
# Rotate our log file every week on Sunday at midnight
<Schedule>
When @weekly
Exec if file_exists('%LOGFILE%') file_cycle('%LOGFILE%', 8);
</Schedule>
</Extension>
<Extension _gelf>
Module xm_gelf
</Extension>
# This example would filter the Windows Event Logs to capture only Network and Interactive logons
# Sources:
# - https://docs.nxlog.co/integrate/windows-eventlog.html
# - https://eventlogxp.com/blog/logon-type-what-does-it-mean/
<Input winEvents>
Module im_msvistalog
Query <QueryList>\
<Query Id="0">\
<Select Path="Security">*[System[Level=0 and (EventID=4624 or EventID=4647)]]</Select>\
</Query>\
</QueryList>
<Exec>
if ($TargetUserName == "SYSTEM" OR $LogonType in ("4", "5", "7", "9"))
drop();
</Exec>
</Input>
<Output send_graylog>
Module om_tcp
Host 0.0.100.88
Port 12201
OutputType GELF_TCP
</Output>
<Processor norepeat>
Module pm_norepeat
CheckFields Message
</Processor>
<Route out>
Path winEvents => norepeat => send_graylog
</Route>