commit 74656f9d8d9dc4311b8da16458c3765e58694da2 Author: CDN18 Date: Wed Dec 11 19:30:02 2024 +0800 init diff --git a/idc-cn.ps1 b/idc-cn.ps1 new file mode 100644 index 0000000..aba8b0d --- /dev/null +++ b/idc-cn.ps1 @@ -0,0 +1,34 @@ +go run main.go --minify ` + AS134963 ` + AS37963 ` + AS45102 ` + AS132203 ` + AS132591 ` + AS137876 ` + AS45090 ` + AS131444 ` + AS136907 ` + AS141180 ` + AS151610 ` + AS200756 ` + AS206204 ` + AS206798 ` + AS265443 ` + AS55990 ` + AS63655 ` + AS63727 ` + AS137787 ` + AS137753 ` + AS131486 ` + AS55967 ` + AS38365 ` + AS396986 ` + AS137775 ` + AS59019 ` + AS137280 ` + AS59077 ` + AS45062 ` + AS137263 ` + AS131659 ` + AS55962 ` + AS140633 diff --git a/main.go b/main.go new file mode 100644 index 0000000..7424617 --- /dev/null +++ b/main.go @@ -0,0 +1,254 @@ +package main + +import ( + "compress/gzip" + "encoding/json" + "fmt" + "io" + "math/rand" + "net/http" + "os" + "sort" + "strings" + "time" +) + +type OrgResponse struct { + Orgname string `json:"orgname"` + Source string `json:"source"` + Cached bool `json:"cached"` +} + +type PrefixResponse struct { + Prefixes []struct { + Prefix string `json:"Prefix"` + Count int `json:"Count"` + Total int `json:"Total"` + } `json:"prefixes"` +} + +func main() { + if len(os.Args) < 2 { + fmt.Println("Usage: go run main.go [--ipv4-only|--ipv6-only] [--minify] [AS_NUMBER2 ...]") + fmt.Println("Options:") + fmt.Println(" --ipv4-only Only output IPv4 prefixes") + fmt.Println(" --ipv6-only Only output IPv6 prefixes") + fmt.Println(" --minify Output minified format to ip-asn-minified.txt") + os.Exit(1) + } + + // Parse flags + var ipv4Only, ipv6Only, minify bool + var asNumbers []string + + // Process arguments + for _, arg := range os.Args[1:] { + switch arg { + case "--ipv4-only": + ipv4Only = true + case "--ipv6-only": + ipv6Only = true + case "--minify": + minify = true + default: + asNumbers = append(asNumbers, arg) + } + } + + if ipv4Only && ipv6Only { + fmt.Println("Error: Cannot use both --ipv4-only and --ipv6-only at the same time") + os.Exit(1) + } + + if len(asNumbers) == 0 { + fmt.Println("Error: No AS numbers provided") + os.Exit(1) + } + + // Create output file + outputFile, err := os.Create("ip-asn.txt") + if err != nil { + fmt.Printf("Error creating output file: %v\n", err) + return + } + defer outputFile.Close() + + // Create minified output file if needed + var minifiedFile *os.File + if minify { + minifiedFile, err = os.Create("ip-asn-minified.txt") + if err != nil { + fmt.Printf("Error creating minified output file: %v\n", err) + return + } + defer minifiedFile.Close() + } + + // Create HTTP client + client := &http.Client{} + + // Process each AS number + for i, arg := range asNumbers { + asNumber := strings.ToLower(strings.TrimPrefix(strings.TrimPrefix(arg, "AS"), "as")) + fmt.Printf("Processing AS%s (%d/%d)...\n", asNumber, i+1, len(asNumbers)) + + // Random wait between requests (1-3 seconds) + if i > 0 { + waitTime := time.Duration(1000+rand.Intn(2000)) * time.Millisecond + fmt.Printf("Waiting for %v before next request...\n", waitTime) + time.Sleep(waitTime) + } + + // Write AS separator and header + if i > 0 { + fmt.Fprintf(outputFile, "\n") + } + + // Get organization name + fmt.Printf("Fetching organization info for AS%s...\n", asNumber) + orgReq, err := http.NewRequest("GET", fmt.Sprintf("https://bgp.he.net/orgname/as%s", asNumber), nil) + if err != nil { + fmt.Printf("Error creating request: %v\n", err) + continue + } + + // Set required headers + orgReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:133.0) Gecko/20100101 Firefox/133.0") + orgReq.Header.Set("Accept", "*/*") + orgReq.Header.Set("Accept-Language", "en-US,en;q=0.5") + orgReq.Header.Set("Accept-Encoding", "gzip") + orgReq.Header.Set("Referer", fmt.Sprintf("https://bgp.he.net/AS%s", asNumber)) + + orgResp, err := client.Do(orgReq) + if err != nil { + fmt.Printf("Error making request: %v\n", err) + continue + } + defer orgResp.Body.Close() + + orgData, err := readResponse(orgResp) + if err != nil { + fmt.Printf("Error reading response: %v\n", err) + continue + } + + var orgInfo OrgResponse + if err := json.Unmarshal(orgData, &orgInfo); err != nil { + fmt.Printf("Error parsing JSON: %v\n", err) + continue + } + + fmt.Fprintf(outputFile, "# =====================================\n") + fmt.Fprintf(outputFile, "# AS%s Prefixes\n", asNumber) + fmt.Fprintf(outputFile, "# Organization: %s\n", orgInfo.Orgname) + fmt.Fprintf(outputFile, "# =====================================\n\n") + + // Get prefixes + fmt.Printf("Fetching prefixes for AS%s...\n", asNumber) + prefixReq, err := http.NewRequest("GET", fmt.Sprintf("https://bgp.he.net/super-lg/report/api/v1/prefixes/originated/%s", asNumber), nil) + if err != nil { + fmt.Printf("Error creating request: %v\n", err) + continue + } + + // Set the same headers for prefix request + prefixReq.Header = orgReq.Header + + prefixResp, err := client.Do(prefixReq) + if err != nil { + fmt.Printf("Error making request: %v\n", err) + continue + } + defer prefixResp.Body.Close() + + prefixData, err := readResponse(prefixResp) + if err != nil { + fmt.Printf("Error reading response: %v\n", err) + continue + } + + var prefixInfo PrefixResponse + if err := json.Unmarshal(prefixData, &prefixInfo); err != nil { + fmt.Printf("Error parsing JSON: %v\n", err) + continue + } + + // Separate IPv4 and IPv6 prefixes + var ipv4Prefixes []string + var ipv6Prefixes []string + + for _, p := range prefixInfo.Prefixes { + if strings.Contains(p.Prefix, ":") { + ipv6Prefixes = append(ipv6Prefixes, p.Prefix) + } else { + ipv4Prefixes = append(ipv4Prefixes, p.Prefix) + } + } + + // Sort prefixes + sort.Strings(ipv4Prefixes) + sort.Strings(ipv6Prefixes) + + // Write to minified file if enabled + if minify { + if i > 0 { + fmt.Fprint(minifiedFile, " ") + } + if !ipv6Only { + for i, prefix := range ipv4Prefixes { + if i > 0 { + fmt.Fprint(minifiedFile, " ") + } + fmt.Fprint(minifiedFile, prefix) + } + } + if !ipv4Only && len(ipv6Prefixes) > 0 { + if len(ipv4Prefixes) > 0 && !ipv6Only { + fmt.Fprint(minifiedFile, " ") + } + for i, prefix := range ipv6Prefixes { + if i > 0 { + fmt.Fprint(minifiedFile, " ") + } + fmt.Fprint(minifiedFile, prefix) + } + } + } + + // Write IPv4 prefixes + if len(ipv4Prefixes) > 0 && !ipv6Only { + fmt.Fprintf(outputFile, "## AS%s - %s - IPv4 Prefixes\n", asNumber, orgInfo.Orgname) + for _, prefix := range ipv4Prefixes { + fmt.Fprintln(outputFile, prefix) + } + } + + // Write IPv6 prefixes + if len(ipv6Prefixes) > 0 && !ipv4Only { + if len(ipv4Prefixes) > 0 && !ipv6Only { + fmt.Fprintln(outputFile, "") + } + fmt.Fprintf(outputFile, "## AS%s - %s - IPv6 Prefixes\n", asNumber, orgInfo.Orgname) + for _, prefix := range ipv6Prefixes { + fmt.Fprintln(outputFile, prefix) + } + } + + fmt.Printf("Completed processing AS%s\n", asNumber) + } + + fmt.Println("All AS numbers processed successfully!") +} + +func readResponse(resp *http.Response) ([]byte, error) { + var reader io.ReadCloser = resp.Body + if resp.Header.Get("Content-Encoding") == "gzip" { + var err error + reader, err = gzip.NewReader(resp.Body) + if err != nil { + return nil, fmt.Errorf("error creating gzip reader: %v", err) + } + defer reader.Close() + } + return io.ReadAll(reader) +}