Splunk Search

Perform a cidrmatch against a network CIDR retrieved from an inputlookup

seaofdreams1978
Engager

Hi All,

We run searches against logs that return, as part of the dataset, IP addresses.

We basically want to know what network and VLAN a given address belongs to so I created a CSV file that contains the following:

network          vlan   name

10.1.1.0/24   12      Server Network

10.1.2.0/24   13      Printer Network

So I'd like to pull in the CSV data and perform a cidrmatch against it using each IP address the search comes across.

If there is no match I want the fields to just return "No Data" so we can then go and update the CSV with anything missing.

As a test I've done the following:

| inputlookup Network_VLAN_Names.csv | fields network vlan name| where NOT isnull(network)
| dest_ip="10.1.1.21"
| foreach network [eval subnet=if(cidrmatch('<<FIELD>>', dest_ip), <<FIELD>>, "No Match")]

| search subnet!="No Match"

| table _time dest_ip vlan name

| sort _time asc

The first issue is that if there is no match, the row isn't returned all (I just want particular fields in a row of returned data to reflect the VLAN and friendly name of the network (if available in the CSV), not for the row to not be available.

Also when I've tried using:

<base search>

| append [ inputlookup Network_VLAN_Names.csv | fields network vlan name| where NOT isnull(network) ]
| foreach network [eval subnet=if(cidrmatch('<<FIELD>>', dest_ip), <<FIELD>>, "No Match")]

| search subnet!="No Match"

| table _time dest_ip vlan name

| sort _time asc

I get nothing back...

There's probably a simple solution to this but I'm not seeing it!

Any help would be much appreciated.

Labels (1)
0 Karma
1 Solution

Richfez
SplunkTrust
SplunkTrust

So, a couple of things.

First, and primarily, I'd switch the csv file /inputlookup into a regular cidr based lookup.

Settings/Lookups/Lookup Definitions (the file's already there so you don't have to add it in "lookup table files").

Add a new lookup definition, name it "networks" or similar, pick your file.

THEN click advanced options.  On "Match type" type in "CIDR(network)" to tell it to cidrmatch on the csv file's field "network."

Then here's a run anywhere search that creates three ip addresses (each in their own event), then uses the lookup we just created to match it to a network.

| makeresults
| eval ip = "192.168.1.12,10.11.12.13,192.168.2.99"
| makemv delim="," ip
| mvexpand ip
| lookup networks network as ip output name
| fillnull value="No Match" name

I do it this way because if you were, say, matching against firewall data, you could replace the first four lines (makeresults through mvexpand) with whatever search you had that displayed an IP address, then modify the lookup slightly and it should work on data of pretty much unbounded size, and quickly. 

In your case, if dest_ip is the field to use, you'd use something like

index=firewall sourcetype=cisco:asa blah blah 
| lookup networks network as dest_ip output name
| fillnull value="No Match" name
| table dest_ip name

 

And obviously, that last line can be changed to `| stats count by name` or any number of other things.

 

For reference, my networks.csv looks like this:

network,name
192.168.1.0/24,home
192.168.2.0/24,guest

 and the transforms.conf entry looks like

[networks]
batch_index_query = 0
case_sensitive_match = 1
filename = networks.csv
match_type = CIDR(network)

 

View solution in original post

0 Karma

seaofdreams1978
Engager

Perfect, worked like a charm and very fast!

Really appreciate the assistance and the fast response!

0 Karma

Richfez
SplunkTrust
SplunkTrust

So, a couple of things.

First, and primarily, I'd switch the csv file /inputlookup into a regular cidr based lookup.

Settings/Lookups/Lookup Definitions (the file's already there so you don't have to add it in "lookup table files").

Add a new lookup definition, name it "networks" or similar, pick your file.

THEN click advanced options.  On "Match type" type in "CIDR(network)" to tell it to cidrmatch on the csv file's field "network."

Then here's a run anywhere search that creates three ip addresses (each in their own event), then uses the lookup we just created to match it to a network.

| makeresults
| eval ip = "192.168.1.12,10.11.12.13,192.168.2.99"
| makemv delim="," ip
| mvexpand ip
| lookup networks network as ip output name
| fillnull value="No Match" name

I do it this way because if you were, say, matching against firewall data, you could replace the first four lines (makeresults through mvexpand) with whatever search you had that displayed an IP address, then modify the lookup slightly and it should work on data of pretty much unbounded size, and quickly. 

In your case, if dest_ip is the field to use, you'd use something like

index=firewall sourcetype=cisco:asa blah blah 
| lookup networks network as dest_ip output name
| fillnull value="No Match" name
| table dest_ip name

 

And obviously, that last line can be changed to `| stats count by name` or any number of other things.

 

For reference, my networks.csv looks like this:

network,name
192.168.1.0/24,home
192.168.2.0/24,guest

 and the transforms.conf entry looks like

[networks]
batch_index_query = 0
case_sensitive_match = 1
filename = networks.csv
match_type = CIDR(network)

 

0 Karma
Get Updates on the Splunk Community!

Welcome to the Splunk Community!

(view in My Videos) We're so glad you're here! The Splunk Community is place to connect, learn, give back, and ...

Tech Talk | Elevating Digital Service Excellence: The Synergy of Splunk RUM & APM

Elevating Digital Service Excellence: The Synergy of Real User Monitoring and Application Performance ...

Adoption of RUM and APM at Splunk

    Unleash the power of Splunk Observability   Watch Now In this can't miss Tech Talk! The Splunk Growth ...