Splunk Search

How to match an IP address to a lookup with IP ranges?

ejwade
Contributor

I have an IP field that I'm trying to match against a lookup that contains DHCP ranges.

For example, assume the lookup contains the following:

Start_Address,End_Address
10.0.0.5,10.0.0.254
10.2.0.5,10.3.0.254
10.4.0.5,10.4.0.254

When matching the IP field, 10.0.0.10 would match, but 10.0.0.2 would not. That said, simply determining the CIDR notation (10.0.0.0/24) won't work. I've consider enumerating all IPs, resulting in a huge lookup, but I'm wondering if anyone has any other ideas.

Labels (1)
0 Karma
1 Solution

ejwade
Contributor

@yuanliuthis is a great approach. However, I need to be able to do this in SPL at search time.

I was able to develop a little external lookup to do this, using the native ipaddress Python module.

For those of you interested, here's the Python file "cidr_lookup.py".

 

#!/usr/bin/env python

from __future__ import print_function
import csv
import ipaddress
import sys


# Given start and end IP addresses, return the CIDRs
def lookup(ip_start, ip_end):
    try:
        cidrs = [str(ipaddr) for ipaddr in ipaddress.summarize_address_range(
            ipaddress.IPv4Address(ip_start),
            ipaddress.IPv4Address(ip_end)
            )
        ]
        cidr_list = ','.join(cidrs)
        return cidr_list
    except:
        return ''


def main():
    if len(sys.argv) != 4:
        print("Usage: python cidr_lookup.py "
              "[ip_start field] [ip_end field] [cidr_list field]")
        sys.exit(1)

    ip_start_field = sys.argv[1]
    ip_end_field = sys.argv[2]
    cidr_list_field = sys.argv[3]

    infile = sys.stdin
    outfile = sys.stdout

    r = csv.DictReader(infile)
    header = r.fieldnames

    w = csv.DictWriter(outfile, fieldnames=header)
    w.writeheader()

    for result in r:
        if result[ip_start_field] and result[ip_end_field]:
            result[cidr_list_field] = lookup(result[ip_start_field],
                                             result[ip_end_field])
            if result[cidr_list_field]:
                w.writerow(result)


main()

 

Here's the transforms.conf.

 

[cidrlookup]
external_cmd = cidr_lookup.py ip_start ip_end cidr_list
fields_list = ip_start, ip_end, cidr_list

 

Here's a screenshot of the lookup in use.

ejwade_1-1685501790520.png

 

View solution in original post

0 Karma

yuanliu
SplunkTrust
SplunkTrust

What do you mean the CIDR notation won't work?  I break down my DHCP range into CIDR notations and everything works perfectly.

10.0.0.5 - 10.0.0.254
10.0.0.5/32
10.0.0.6/31
10.0.0.8/29
10.0.0.16/28
10.0.0.32/27
10.0.0.64/26
10.0.0.128/26
10.0.0.192/27
10.0.0.224/28
10.0.0.240/29
10.0.0.248/30
10.0.0.252/31
10.0.0.254/32
10.2.0.5 - 10.3.0.254
10.2.0.5/32
10.2.0.6/31
10.2.0.8/29
10.2.0.16/28
10.2.0.32/27
10.2.0.64/26
10.2.0.128/25
10.2.1.0/24
10.2.2.0/23
10.2.4.0/22
10.2.8.0/21
10.2.16.0/20
10.2.32.0/19
10.2.64.0/18
10.2.128.0/17
10.3.0.0/25
10.3.0.128/26
10.3.0.192/27
10.3.0.224/28
10.3.0.240/29
10.3.0.248/30
10.3.0.252/31
10.3.0.254/32
10.3.0.5 - 10.4.0.254
10.3.0.5/32
10.3.0.6/31
10.3.0.8/29
10.3.0.16/28
10.3.0.32/27
10.3.0.64/26
10.3.0.128/25
10.3.1.0/24
10.3.2.0/23
10.3.4.0/22
10.3.8.0/21
10.3.16.0/20
10.3.32.0/19
10.3.64.0/18
10.3.128.0/17
10.4.0.0/25
10.4.0.128/26
10.4.0.192/27
10.4.0.224/28
10.4.0.240/29
10.4.0.248/30
10.4.0.252/31
10.4.0.254/32

You can calculate these CIDR's using for example https://www.ipaddressguide.com/cidr

Tags (1)

ejwade
Contributor

@yuanliuthis is a great approach. However, I need to be able to do this in SPL at search time.

I was able to develop a little external lookup to do this, using the native ipaddress Python module.

For those of you interested, here's the Python file "cidr_lookup.py".

 

#!/usr/bin/env python

from __future__ import print_function
import csv
import ipaddress
import sys


# Given start and end IP addresses, return the CIDRs
def lookup(ip_start, ip_end):
    try:
        cidrs = [str(ipaddr) for ipaddr in ipaddress.summarize_address_range(
            ipaddress.IPv4Address(ip_start),
            ipaddress.IPv4Address(ip_end)
            )
        ]
        cidr_list = ','.join(cidrs)
        return cidr_list
    except:
        return ''


def main():
    if len(sys.argv) != 4:
        print("Usage: python cidr_lookup.py "
              "[ip_start field] [ip_end field] [cidr_list field]")
        sys.exit(1)

    ip_start_field = sys.argv[1]
    ip_end_field = sys.argv[2]
    cidr_list_field = sys.argv[3]

    infile = sys.stdin
    outfile = sys.stdout

    r = csv.DictReader(infile)
    header = r.fieldnames

    w = csv.DictWriter(outfile, fieldnames=header)
    w.writeheader()

    for result in r:
        if result[ip_start_field] and result[ip_end_field]:
            result[cidr_list_field] = lookup(result[ip_start_field],
                                             result[ip_end_field])
            if result[cidr_list_field]:
                w.writerow(result)


main()

 

Here's the transforms.conf.

 

[cidrlookup]
external_cmd = cidr_lookup.py ip_start ip_end cidr_list
fields_list = ip_start, ip_end, cidr_list

 

Here's a screenshot of the lookup in use.

ejwade_1-1685501790520.png

 

0 Karma
Get Updates on the Splunk Community!

Introducing the Splunk Community Dashboard Challenge!

Welcome to Splunk Community Dashboard Challenge! This is your chance to showcase your skills in creating ...

Wondering How to Build Resiliency in the Cloud?

IT leaders are choosing Splunk Cloud as an ideal cloud transformation platform to drive business resilience,  ...

Updated Data Management and AWS GDI Inventory in Splunk Observability

We’re making some changes to Data Management and Infrastructure Inventory for AWS. The Data Management page, ...