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!

.conf24 | Day 0

Hello Splunk Community! My name is Chris, and I'm based in Canberra, Australia's capital, and I travelled for ...

Enhance Security Visibility with Splunk Enterprise Security 7.1 through Threat ...

(view in My Videos)Struggling with alert fatigue, lack of context, and prioritization around security ...

Troubleshooting the OpenTelemetry Collector

  In this tech talk, you’ll learn how to troubleshoot the OpenTelemetry collector - from checking the ...