Windows IP Address Monitoring

I’ve come across a couple of reasons to have a correlation between the IP Address (at a point in time) and a hostname. For most normal cases, you can use the nslookup script to do a reverse lookup. However, sometimes it’s a good idea to get the list and store it in a lookup. Unfortunately, this is actually a difficult piece of information to get outside of the DNS system. Here are my favorite ways of doing it.

Firstly, there is the PowerShell way. This uses the SA-ModularInput-PowerShell addon to run a PowerShell command to get the list for you. Here is the function you need:

function Get-LocalIPAddress
    $AdapterSet = Get-WmiObject -Class Win32_NetworkAdapterConfiguration
    $IPAddressSet = @()
    foreach ($adapter in $AdapterSet) {
        if ($adapter.IPAddress -ne $null) {
            foreach ($ipaddress in $adapter.IPAddress) {
                $IPAddressSet = $IPAddressSet + $ipaddress

With this function, you can create a data input script like this:

$HostInfo = New-Object PSObject
$HostInfo | Add-Member -PassThru -MemberType NoteProperty IPAddressList -Value ((Get-LocalIPAddress) -join ",")

Add the function and the script together, place in a *.ps1 file in your bin directory and utilize the SA-ModularInput-PowerShell scheduling feature to run this once a day. You will get one event per day per host with the list of IP Addresses. Once you have this, you can set up a saved search like this:

| eval IPAddress=split(IPAddressList,",") 
| mvexpand IPAddress 
| table IPAddress,host 
| outputlookup IPAddressToHost

This is nice if you are doing other things with PowerShell and has the advantage of a limited search range – you only need to search over the last 24 hours (assuming you are running the script once a day) in order to generate the lookup. However, it does require another app on your endpoints and the requirement for installing PowerShell 3 and .NET Framework 4.5 on your systems. This is something that is not always feasible. For that reason we have another way – one using just the regular data inputs provided with the Splunk Universal Forwarder. You might be forgiven here for guessing WMI. WMI has a great WQL command for retrieving the list and you can try it for yourself:

Get-WmiObject -query 'SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled="TRUE"'

However, you will note here that the IP Address List field returns an array. The Splunk WMI reader can’t deal with arrays today. Fortunately, WMI isn’t the only place where this information is stored. It’s also stored in the registry in the HKLM hive. You can set up a data input as follows:


Note that the syntax I have provided works with Splunk 6 Universal Forwarders. If you have an earlier version, you will need to convert this to the older regmon-filters.conf syntax. Every day, the WinRegMon will do a baseline crawl through this section. An example event is here:

11/13/2013 07:57:16.548

There are a couple of interesting things here. Firstly, you will note that there is a GUID in the key_path – this is a unique ID for the interface, so it’s definitely something we are interested in. Secondly, note the timestamp. The baseline timestamp is not the time when the baseline is captured, but rather the last time the key has been updated. You may see duplicate baseline events for the same key with the same timestamp if the key has not been updated. In the case of IP addresses, that is certainly possible. To turn this into a lookup, we need to do some work. The first task is to extract the GUID, which is conveniently located between two curly-braces in the key_path field. The second is to get a link between host, GUID and IP Address, which we can do with a simple stats call. Finally, we need to bring in the existing lookup table since the events may be generated way in the past. Here is how I do it:

sourcetype=WinRegistry registry_type="baseline" key_path="*IPAddress"
| rex field=key_path "{(?<GUID>[^}]+"
| stats latest(_time) as _time,latest(data) as IPAddress by host,GUID
| inputlookup append=T IPAddressToHost
| sort _time
| stats latest(_time) as _time,latest(data) as IPAddress by host,GUID
| outputlookup IPAddressToHost

You can use this version of the lookup the same way as the PowerShell version, but it has two extra fields – the _time field is the time that the interface last updated its IP Address, and the GUID is the internal GUID of the interface. You can use it wherever you have an IP address like this:

sourcetype=iis | lookup IPAddressToHost IPAddress as src_ip OUTPUTNEW host AS src_host
Posted by