Skip to content

Instantly share code, notes, and snippets.

@Zhwt
Created June 17, 2024 03:35
Show Gist options
  • Save Zhwt/dd29491b432d530daa2d49d57c7cb171 to your computer and use it in GitHub Desktop.
Save Zhwt/dd29491b432d530daa2d49d57c7cb171 to your computer and use it in GitHub Desktop.
Go tool for merging CIDR ranges.
package main
import (
"bufio"
"fmt"
"log"
"net/http"
"net/netip"
"os"
"go4.org/netipx"
)
// readCIDRsFromURL reads CIDR ranges from a URL.
func readCIDRsFromURL(url string) ([]netip.Prefix, error) {
log.Println("Reading CIDRs from URL: ", url)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
var cidrs []netip.Prefix
scanner := bufio.NewScanner(resp.Body)
for scanner.Scan() {
line := scanner.Text()
cidr, err := netip.ParsePrefix(line)
if err != nil {
return nil, err
}
cidrs = append(cidrs, cidr)
}
return cidrs, scanner.Err()
}
// readCIDRsFromFile reads CIDR ranges from a file.
func readCIDRsFromFile(filename string) ([]netip.Prefix, error) {
log.Println("Reading CIDRs from file: ", filename)
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
var cidrs []netip.Prefix
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
cidr, err := netip.ParsePrefix(line)
if err != nil {
return nil, err
}
cidrs = append(cidrs, cidr)
}
return cidrs, scanner.Err()
}
// writeCIDRsToFile writes CIDR ranges to a file.
func writeCIDRsToFile(filename string, cidrs []netip.Prefix) error {
log.Println("Writing CIDRs to file: ", filename)
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
writer := bufio.NewWriter(file)
for _, cidr := range cidrs {
_, err := writer.WriteString(cidr.String() + "\n")
if err != nil {
return err
}
}
return writer.Flush()
}
// mergeCIDRs merges and returns the unified list of CIDR ranges.
func mergeCIDRs(cidrs []netip.Prefix) []netip.Prefix {
var b netipx.IPSetBuilder
for _, cidr := range cidrs {
b.AddPrefix(cidr)
}
// ignore errors on purpose to avoid errors in single cidr causing fail output,
// see comment for IPSetBuilder.IPSet()
ipset, _ := b.IPSet()
return ipset.Prefixes()
}
func main() {
// Define your sources here.
urlSources := []string{
"https://www.ipdeny.com/ipblocks/data/aggregated/cn-aggregated.zone",
"https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt",
}
fileSources := []string{
//"ip1.txt",
//"ip2.txt",
}
fileSources = os.Args[1:]
var allCIDRs []netip.Prefix
// Read CIDRs from URL sources.
for _, url := range urlSources {
cidrs, err := readCIDRsFromURL(url)
if err != nil {
fmt.Printf("Error reading CIDRs from URL %s: %v\n", url, err)
continue
}
allCIDRs = append(allCIDRs, cidrs...)
}
// Read CIDRs from file sources.
for _, file := range fileSources {
cidrs, err := readCIDRsFromFile(file)
if err != nil {
fmt.Printf("Error reading CIDRs from file %s: %v\n", file, err)
continue
}
allCIDRs = append(allCIDRs, cidrs...)
}
// Merge CIDRs.
log.Println("Merging CIDRs...")
mergedCIDRs := mergeCIDRs(allCIDRs)
// Output the merged CIDRs.
//fmt.Println("Merged CIDRs:")
//for _, cidr := range mergedCIDRs {
// fmt.Println(cidr)
//}
// Write the merged CIDRs to a file.
err := writeCIDRsToFile("merged_cidrs.txt", mergedCIDRs)
if err != nil {
fmt.Printf("Error writing CIDRs to file: %v\n", err)
return
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment