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!

Share Your Ideas & Meet the Lantern team at .Conf! Plus All of This Month’s New ...

Splunk Lantern is Splunk’s customer success center that provides advice from Splunk experts on valuable data ...

Combine Multiline Logs into a Single Event with SOCK: a Step-by-Step Guide for ...

Combine multiline logs into a single event with SOCK - a step-by-step guide for newbies Olga Malita The ...

Stay Connected: Your Guide to May Tech Talks, Office Hours, and Webinars!

Take a look below to explore our upcoming Community Office Hours, Tech Talks, and Webinars this month. This ...