Skip to content

haoel/ipsearch

Repository files navigation

IP Search

This is a simple library to search for IP addresses for two different IP Databases: IP CIDR List and IP Geo CVS, which go

Table of Contents

1. IP Database

This library can deal with the following IP databases:

  • china_ip_list.txt: A list of IP addresses in China. This list is from the China IP List project.

  • asn-country-ipv4.txt: A list of IP addresses and their ASN and country information. This list is from the IP Location DB project.

To update these two data files, run the following script:

./data/update.sh

Note

  • The CIDRs file must be a plain text file, and each line is a CIDR.
  • The CIDRs cannot be overlapped.

2. Usage

2.1 Check an IP address is in the IP CIDR list

package main

import (
	"fmt"
	"github.com/haoel/ipsearch"
)

func main() {
	search, err := ipsearch.NewIPSearchWithFile("./data/china_ip_list.txt", ipsearch.CIDR)
	if err != nil {
		panic(err)
	}

	ipStr := "114.114.114.114"
	ip := search.Search(ipStr)
	if ip != nil {
		fmt.Printf("IP [%s] is in China\n", ipStr)
	} else {
		fmt.Printf("IP [%s] is not China\n", ipStr)
	}
}

It also supports reading the URL files:

url := "https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt"
search, err := ipsearch.NewIPSearchWithURL(url)

2.2 Get the Country Code of an IP address

package main

import (
	"fmt"
	"github.com/haoel/ipsearch"
)

func main() {
	search, err := ipsearch.NewIPSearchWithFile("./data/asn-country-ipv4.csv", ipsearch.Geo)
	if err != nil {
		panic(err)
	}
	ipStr := "8.8.8.8"
	ip := search.Search(ipStr)
	if ip != nil {
		fmt.Printf("IP [%s] Country Code: %s\n", ipStr, ip.Country())
	} else {
		fmt.Printf("IP [%s] is not found!\n", ipStr)
	}
}

3. Technical Details

The IP search is using the Hash Table and Binary Search algorithm.

The key of the hash table is the first 8 bits of the IP address, and the value is the sorted list of CIDRs that have the same first 8 bits.

[  1 ] -> [1.0.1.0/24],
          [1.0.2.0/23],
          [1.1.4.0/22]
          ...
[ 14 ] -> [14.0.0.0/21],
          [14.0.12.0/22],
          [14.1.0.0/22]
          ...

The IPRangeMapList is the hash table that stores all of the sorted CIDRs lists.

For the GeoIP database, it gives the start and end IP address, this would across the multiple hash table keys, so we need to split it.

For example, if the IP range is 1.1.0.0 - 3.2.2.255, we need to split it into three ranges:

  • 1.1.0.0 - 1.255.255.255
  • 2.0.0.0 - 2.255.255.255
  • 3.0.0.0 - 3.2..2.255

The split algorithm is in the IPRange.Split() function in the iprange.go file.

Note

And I didn't use the standard net/netip library, because of the following two reasons:

  • We can be free to customize and extend the algorithm
  • We can port the algorithm to other languages easily.

4. License

This project is MIT licensed. See the LICENSE file for details.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published