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!

Introducing the 2024 SplunkTrust!

Hello, Splunk Community! We are beyond thrilled to announce our newest group of SplunkTrust members!  The ...

Introducing the 2024 Splunk MVPs!

We are excited to announce the 2024 cohort of the Splunk MVP program. Splunk MVPs are passionate members of ...

Splunk Custom Visualizations App End of Life

The Splunk Custom Visualizations apps End of Life for SimpleXML will reach end of support on Dec 21, 2024, ...