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.
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)
Perfect, worked like a charm and very fast!
Really appreciate the assistance and the fast response!
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)
Additional idea on this thought is based on baseline of probing network. You can use this information to assign a risk base alert. Just a thought...