### Install Dependencies Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Commands to install optional dependencies for PostgreSQL and UDP resolution. ```bash pip install 'psycopg[binary]' ``` ```bash pip install dnspython ``` -------------------------------- ### CLI invocation example Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Example command to execute the script with specific regions, resolver settings, and output files. ```bash python3 collect_discord_voice_ips.py \ --regions "seattle,frankfurt" \ --resolver udp \ --workers 16 \ --ips-out discovered_ips.txt \ --json-out report.json ``` -------------------------------- ### Example Provider-to-Prefixes Data Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Example dictionary structure for provider-to-prefix mapping. ```python { "aws": [PrefixEntry("192.0.2.0/24", region="us-west-2"), ...], "cloudflare": [PrefixEntry("198.51.100.0/24"), ...], } ``` -------------------------------- ### Sing-box Configuration Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Example configuration snippet for integrating binary rulesets into a Sing-box routing setup. ```json { "route": { "rules": [ { "rule_set": ["geoip-aws"], "outbound": "proxy" }, { "rule_set": ["geoip-cloudflare"], "outbound": "direct" } ], "rule_sets": [ { "tag": "geoip-aws", "type": "ipcidr", "format": "binary", "path": "./aws_singbox_ipv4.srs" }, { "tag": "geoip-cloudflare", "type": "ipcidr", "format": "binary", "path": "./cloudflare_singbox_ipv4.srs" } ] } } ``` -------------------------------- ### Example Domain-to-IPs Data Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Example dictionary structure for domain-to-IP mapping. ```python { "seattle-1.discord.gg": ["1.2.3.4", "2001:db8::1"], "frankfurt-1.discord.gg": ["5.6.7.8"], } ``` -------------------------------- ### Instantiate PrefixEntry objects Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Examples of creating PrefixEntry instances with various CIDR and region configurations. ```python # AWS EC2 range with region entry = PrefixEntry("192.0.2.0/24", region="us-west-2") # No region information entry = PrefixEntry("198.51.100.0/24") # Discord voice host IP (individual /32) entry = PrefixEntry("1.2.3.4/32", region="seattle-1") # IPv6 range entry = PrefixEntry("2001:db8::/32", region="eu-central-1") ``` -------------------------------- ### Instantiate ProviderSpec objects Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Examples of configuring different provider types including CDN, multi-ASN, and deprecated sources. ```python # Simple RIPE-based provider (Cloudflare) provider = ProviderSpec( name="cloudflare", fetcher=lambda: fetch_ripe_prefixes("13335"), is_cdn=True, ) # Multi-ASN provider (Hetzner) provider = ProviderSpec( name="hetzner", fetcher=lambda: ( list(fetch_ripe_prefixes("24940")) + list(fetch_ripe_prefixes("213230")) + list(fetch_ripe_prefixes("212317")) ), is_cdn=True, ) # Non-CDN, optional provider (Discord voice - may return no results) provider = ProviderSpec( name="discord-voice", fetcher=fetch_discord_voice_ranges, is_cdn=False, allow_empty=True, ) # Deprecated provider (still generates outputs, not in "all") provider = ProviderSpec( name="roblox", fetcher=lambda: fetch_ripe_prefixes("22697"), is_cdn=False, is_deprecated=True, ) ``` -------------------------------- ### Example Region-to-Domains Data Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Example dictionary structure for region-to-domain mapping. ```python { "seattle": {"seattle-1.discord.gg", "seattle-2.discord.gg"}, "frankfurt": {"frankfurt-1.discord.gg"}, } ``` -------------------------------- ### Install Workflow Dependencies Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Installs required Python packages for network operations. ```bash python3 -m pip install "psycopg[binary]" dnspython ``` -------------------------------- ### Generate GeoIP Binary Files Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Example command to invoke the generation script for V2Ray binary files. ```bash python3 scripts/generate_geoip_dat.py # Generates: akamai/akamai_geoip.dat, akamai/akamai_geoip_ipv4.dat, ... ``` -------------------------------- ### Run Keenetic conversion CLI Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Examples of executing the conversion script via command line to process specific providers or all available providers. ```bash # Interactive selection python3 scripts/convert_for_keenetic.py # Select specific providers python3 scripts/convert_for_keenetic.py --providers aws cloudflare akamai # Comma-separated input python3 scripts/convert_for_keenetic.py --providers "aws,cloudflare" # All providers, 2048 routes per file python3 scripts/convert_for_keenetic.py --all --max-lines 2048 ``` -------------------------------- ### Per-Provider Directory Structure Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Example of the file organization within a specific provider directory. ```text aws/ ├── aws_plain.txt # Text (IPv4+IPv6) ├── aws_plain_ipv4.txt # Text (IPv4 only) ├── aws_amnezia_ipv4.json # JSON (IPv4 only) ├── aws_geoip.dat # V2Ray (IPv4+IPv6) ├── aws_geoip_ipv4.dat # V2Ray (IPv4 only) ├── aws_singbox.srs # sing-box (IPv4+IPv6) └── aws_singbox_ipv4.srs # sing-box (IPv4 only) ``` -------------------------------- ### GitHub Actions Workflow for sing-box Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Automates the installation of the latest sing-box binary and the execution of ruleset generation scripts. ```yaml - name: Install sing-box env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | tag=$(curl -fs -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/repos/SagerNet/sing-box/releases/latest | jq -r '.tag_name') arch=$(dpkg --print-architecture) package_name="sing-box_${tag#v}_linux_${arch}.deb" package_url="https://github.com/SagerNet/sing-box/releases/download/${tag}/${package_name}" curl -fLo "$package_name" -H "Authorization: token $GITHUB_TOKEN" "$package_url" sudo dpkg -i "$package_name" rm -f "$package_name" - name: Generate sing-box ruleset files run: python3 scripts/generate_sing_box_rulesets.py ``` -------------------------------- ### CSV Data Structure Example Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Sample content of the all.csv file showing the provider, cidr, and region columns. ```csv provider,cidr,region akamai,2.16.0.0/13, akamai,23.0.0.0/12, akamai,23.32.0.0/11, akamai,23.64.0.0/14, aws,1.160.0.0/11,us-west-2 aws,1.192.0.0/11,us-west-2 aws,13.0.0.0/13,eu-west-1 aws,13.32.0.0/14,eu-central-1 aws,13.36.0.0/14,eu-west-1 cloudflare,1.1.1.0/24, cloudflare,1.1.1.0/24, digitalocean,1.1.128.0/18,san ... (continues) ``` -------------------------------- ### Programmatic Usage Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Example of importing and using internal functions to process IP ranges programmatically. ```python from pathlib import Path from convert_for_keenetic import ( _available_providers, _read_ipv4_prefixes, _build_routes, _chunk_lines, _write_chunks, ) repo_root = Path("/workspace/home/cdn-ip-ranges") provider_name = "aws" provider_dir = repo_root / provider_name source_path = provider_dir / f"{provider_name}_plain_ipv4.txt" # Read IPv4 prefixes networks = _read_ipv4_prefixes(source_path) print(f"Loaded {len(networks)} IPv4 networks") # Generate routes routes = _build_routes(networks) print(f"Generated {len(routes)} route commands") # Chunk and write chunks = _chunk_lines(routes, max_lines=1024) _write_chunks(provider_name, chunks) print(f"Wrote {len(chunks)} batch file(s)") ``` -------------------------------- ### Configure V2Ray Routing Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Example JSON configuration for V2Ray routing rules using the GeoIP binary files. ```json { "routing": { "rules": [ { "type": "field", "geoip": ["aws"], "outbound": "proxy" }, { "type": "field", "geoip": ["cloudflare"], "outbound": "direct" } ] } } ``` -------------------------------- ### Combined Outputs Directory Structure Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Example of the file organization for combined provider data. ```text all/ ├── all_plain.txt ├── all_plain_ipv4.txt ├── all_amnezia_ipv4.json ├── all_geoip.dat ├── all_geoip_ipv4.dat ├── all_singbox.srs ├── all_singbox_ipv4.srs └── all.csv # Provider metadata ``` ```text cdn-only/ ├── cdn-only_plain.txt ├── cdn-only_plain_ipv4.txt ├── cdn-only_amnezia_ipv4.json ├── cdn-only_geoip.dat ├── cdn-only_geoip_ipv4.dat ├── cdn-only_singbox.srs └── cdn-only_singbox_ipv4.srs ``` -------------------------------- ### Generated Batch File Content Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Example of the route command structure generated in the output batch files. ```batch route add 1.178.1.0 mask 255.255.255.0 0.0.0.0 route add 1.178.4.0 mask 255.255.252.0 0.0.0.0 route add 1.178.8.0 mask 255.255.252.0 0.0.0.0 ... (1234 total routes) ``` -------------------------------- ### Normalize Prefixes Function Signature Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Example function signature using Iterable[PrefixEntry]. ```python def normalize_prefixes( provider: str, prefixes: Iterable[PrefixEntry] ) -> List[PrefixEntry]: ... ``` -------------------------------- ### Keenetic Batch Script Format Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Example of the route command structure used in Keenetic batch files. Manual gateway replacement is required. ```batch route add 1.178.1.0 mask 255.255.255.0 0.0.0.0 route add 1.178.4.0 mask 255.255.252.0 0.0.0.0 route add 1.178.8.0 mask 255.255.252.0 0.0.0.0 route add 1.178.16.0 mask 255.255.240.0 0.0.0.0 route add 1.178.64.0 mask 255.255.254.0 0.0.0.0 route add 1.178.72.0 mask 255.255.248.0 0.0.0.0 route add 1.178.86.0 mask 255.255.255.0 0.0.0.0 route add 1.178.88.0 mask 255.255.248.0 0.0.0.0 ... (continues) route add 1.178.100.0 mask 255.255.252.0 0.0.0.0 route add 1.178.172.0 mask 255.255.254.0 0.0.0.0 ``` -------------------------------- ### Implement Sequential Pipeline Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/INDEX.md Demonstrates the linear data transformation flow from fetching to writing provider outputs. ```python raw = fetch_aws_ranges() normalized = normalize_prefixes("aws", raw) aggregated = aggregate_prefixes("aws", normalized) write_provider_outputs("aws", aggregated) ``` -------------------------------- ### Execute main generation script Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Runs the generation process for all providers, optionally specifying a custom path to the sing-box binary. ```bash # Using sing-box from PATH python3 scripts/generate_sing_box_rulesets.py # Using custom sing-box binary location python3 scripts/generate_sing_box_rulesets.py --sing-box /opt/sing-box/bin/sing-box ``` -------------------------------- ### Configure output files and filtering Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Specify paths for output files and enable filtering for resolved domains only. ```bash --domains-out /tmp/discord_domains.txt --ips-out /tmp/discord_ips.txt --json-out /tmp/discord_report.json --resolved-domains-only ``` -------------------------------- ### Run update_cdn_lists.py Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Executes the script with hard-coded provider settings. ```bash python3 scripts/update_cdn_lists.py ``` -------------------------------- ### Generate rulesets via CLI Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Execute the generation script using the default sing-box binary found in the system PATH. ```bash cd /workspace/home/cdn-ip-ranges python3 scripts/generate_sing_box_rulesets.py ``` -------------------------------- ### Programmatic Usage of CDN Lists Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/INDEX.md Demonstrates how to import and use the internal library functions to fetch and aggregate AWS IP ranges. ```python from pathlib import Path from update_cdn_lists import ( fetch_aws_ranges, normalize_prefixes, aggregate_prefixes ) prefixes = fetch_aws_ranges() normalized = normalize_prefixes("aws", prefixes) aggregated = aggregate_prefixes("aws", normalized) print(f"Generated {len(aggregated)} ranges for AWS") for entry in aggregated[:5]: print(f" {entry.cidr}") ``` -------------------------------- ### Execute GeoIP generation via CLI Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Demonstrates running the generation script directly or splitting the process into configuration generation and compilation steps. ```bash # Generate and compile immediately python3 scripts/generate_geoip_dat.py # Generate config only, inspect it, then compile separately python3 scripts/generate_geoip_dat.py --config-only --config-path /tmp/cfg.json go run github.com/v2fly/geoip@latest -c /tmp/cfg.json ``` -------------------------------- ### Run collect_discord_voice_ips.py Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Base command for collecting Discord voice IP ranges. ```bash python3 scripts/collect_discord_voice_ips.py [OPTIONS] ``` -------------------------------- ### Inspect Generation Configuration Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Export the generation configuration to a JSON file for review before executing the build process. ```bash python3 scripts/generate_geoip_dat.py --config-only --config-path /tmp/geoip-cfg.json cat /tmp/geoip-cfg.json ``` -------------------------------- ### Configure performance and limits Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Adjust worker threads, timeouts, retries, and domain limits for DNS resolution. ```bash --workers 16 --timeout 5.0 --retries 3 --max-domains 500 --progress-every 100 ``` -------------------------------- ### Define Provider Configuration Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/INDEX.md Shows how providers are defined as immutable specifications using lambda functions or direct references. ```python providers = ( ProviderSpec("akamai", lambda: fetch_ripe_prefixes("20940")), ProviderSpec("aws", fetch_aws_ranges), ... ) ``` -------------------------------- ### Run Interactive Mode Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Execute the script in interactive mode to select providers via command line input. ```bash cd /workspace/home/cdn-ip-ranges python3 scripts/convert_for_keenetic.py # Output: # Available providers: # akamai, aws, bunny, ..., vercel # Enter provider names separated by commas. # > aws cloudflare # aws: wrote 1234 routes to aws_keenetic.bat # cloudflare: wrote 5678 routes to cloudflare_keenetic.bat ``` -------------------------------- ### View Output Directory Structure Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Displays the organization of generated IP range files by provider and format. ```text / ├── akamai/ │ ├── akamai_plain.txt # All prefixes (IPv4+IPv6) │ ├── akamai_plain_ipv4.txt # IPv4 only │ ├── akamai_amnezia_ipv4.json # Amnezia VPN format │ ├── akamai_geoip.dat # V2Ray GeoIP (IPv4+IPv6) │ ├── akamai_geoip_ipv4.dat # V2Ray GeoIP (IPv4 only) │ ├── akamai_singbox.srs # sing-box ruleset (IPv4+IPv6) │ └── akamai_singbox_ipv4.srs # sing-box ruleset (IPv4 only) ├── aws/ │ ├── aws_plain.txt │ ├── aws_plain_ipv4.txt │ ├── aws_amnezia_ipv4.json │ ├── aws_geoip.dat │ ├── aws_geoip_ipv4.dat │ ├── aws_singbox.srs │ └── aws_singbox_ipv4.srs ├── ... (25+ provider directories) ├── all/ │ ├── all_plain.txt # Combined from all non-deprecated providers │ ├── all_plain_ipv4.txt │ ├── all_amnezia_ipv4.json │ ├── all_geoip.dat │ ├── all_geoip_ipv4.dat │ ├── all_singbox.srs │ ├── all_singbox_ipv4.srs │ └── all.csv # Metadata: provider, cidr, region └── cdn-only/ ├── cdn-only_plain.txt # Combined from CDN providers only ├── cdn-only_plain_ipv4.txt ├── cdn-only_amnezia_ipv4.json ├── cdn-only_geoip.dat ├── cdn-only_geoip_ipv4.dat ├── cdn-only_singbox.srs └── cdn-only_singbox_ipv4.srs ``` -------------------------------- ### Set DNS resolver backend Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Choose between public DNS via UDP or the system's local resolver. ```bash python3 scripts/collect_discord_voice_ips.py --resolver system python3 scripts/collect_discord_voice_ips.py --resolver udp ``` -------------------------------- ### Execute GeoIP Generator Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Writes the configuration to a file and triggers the external Go-based generator. ```python config_path = Path("/tmp/geoip-config.json") config_path.write_text(json.dumps(config), encoding="utf-8") run_geoip_generator(config_path) # Generates: akamai/akamai_geoip.dat, akamai/akamai_geoip_ipv4.dat, ... ``` -------------------------------- ### Generate GeoIP Files via CLI Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Execute the generation script to compile all provider .dat files in the project directory. ```bash cd /workspace/home/cdn-ip-ranges python3 scripts/generate_geoip_dat.py ``` -------------------------------- ### Generate provider output files Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Creates multiple output files (plain text and JSON) for a specific provider in a dedicated directory. ```python def write_provider_outputs(provider: str, prefixes: Sequence[PrefixEntry]) -> None ``` ```python prefixes = [ PrefixEntry("192.0.2.0/24"), PrefixEntry("2001:db8::/32"), ] write_provider_outputs("aws", prefixes) # Creates: aws/aws_plain.txt, aws/aws_plain_ipv4.txt, aws/aws_amnezia_ipv4.json ``` -------------------------------- ### Fetch domains from PostgreSQL Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Queries the crt.sh database for valid Discord voice domains. Requires the psycopg library. ```sql SELECT name_value FROM certificate_and_identities WHERE plainto_tsquery('certwatch', '.discord.gg') @@ identities(CERTIFICATE) AND NAME_VALUE ILIKE '%.discord.gg' AND NAME_TYPE = '2.5.4.3' -- commonName AND x509_notAfter(CERTIFICATE) >= now() AT TIME ZONE 'UTC' ``` ```python domains = fetch_ct_domains_from_postgres( host="crt.sh", port=5432, dbname="certwatch", user="guest", connect_timeout=20, retries=3, ) # Returns ~1000-5000 domains like ["brazil-1.discord.gg", "us-east-1.discord.gg", ...] ``` -------------------------------- ### fetch_ct_domains_from_postgres(host, port, dbname, user, connect_timeout, retries) Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Queries the crt.sh PostgreSQL database to retrieve all *.discord.gg certificate domains. ```APIDOC ## fetch_ct_domains_from_postgres(host, port, dbname, user, connect_timeout, retries) ### Description Queries crt.sh PostgreSQL for all *.discord.gg certificate domains. Performs deduplication and sorting on the results. ### Parameters - **host** (str) - Required - PostgreSQL server hostname or IP - **port** (int) - Required - PostgreSQL port - **dbname** (str) - Required - Database name - **user** (str) - Required - PostgreSQL user - **connect_timeout** (int) - Required - Connection timeout in seconds - **retries** (int) - Required - Retry count for transient failures ### Returns - **list[str]** - Sorted, unique domain names matching *.discord.gg ``` -------------------------------- ### Configure sing-box routing rules Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Integrate generated .srs files into a sing-box configuration file using the ipcidr rule set type. ```json { "route": { "rules": [ { "rule_set": ["provider:aws"], "outbound": "proxy" }, { "rule_set": ["provider:cloudflare"], "outbound": "direct" } ], "rule_sets": [ { "tag": "provider:aws", "type": "ipcidr", "format": "binary", "path": "./aws_singbox_ipv4.srs" } ] } } ``` -------------------------------- ### Generate Sing-box Rulesets Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Command to generate binary ruleset files for the Sing-box proxy engine. ```bash python3 scripts/generate_sing_box_rulesets.py # Generates: akamai/akamai_singbox.srs, akamai/akamai_singbox_ipv4.srs, ... ``` -------------------------------- ### Build GeoIP Configuration Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Generates the configuration dictionary required for the GeoIP compilation process. ```python config = build_geoip_config() # config["input"] has ~25 entries # config["output"] has ~50 entries (2 per provider) ``` -------------------------------- ### Discover providers in repository Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Scans the repository root to identify provider directories containing plain text lists. ```python providers = discover_providers(Path("/workspace/home/cdn-ip-ranges")) # Returns: ["akamai", "aws", "bunny", ..., "vercel", "all"] ``` -------------------------------- ### Run Batch Mode Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Execute the script in batch mode using command line arguments for provider selection and line limits. ```bash # Process all providers with default 1024 max lines python3 scripts/convert_for_keenetic.py --all # Process three providers with 512 max routes per file python3 scripts/convert_for_keenetic.py --providers aws,cloudflare,akamai --max-lines 512 ``` -------------------------------- ### Generate rulesets with custom sing-box path Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Specify a custom location for the sing-box binary using the --sing-box flag. ```bash python3 scripts/generate_sing_box_rulesets.py --sing-box /usr/local/bin/sing-box ``` -------------------------------- ### Configure PostgreSQL connection Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Set database connection parameters for crt.sh data retrieval. ```bash --crtsh-db-host crt.sh --crtsh-db-port 5432 --crtsh-db-name certwatch --crtsh-db-user guest --crtsh-db-connect-timeout 30 ``` -------------------------------- ### Main entry point definition Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md The primary function for script execution, handling argument parsing and IP collection logic. ```python def main() -> int ``` -------------------------------- ### Configure Discord regions Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Specify one or more comma-separated regions to match. ```bash python3 scripts/collect_discord_voice_ips.py --regions "seattle,frankfurt,us-east" python3 scripts/collect_discord_voice_ips.py --regions seattle # Single region ``` -------------------------------- ### Discover available providers Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Use this function to identify all providers with valid plaintext IP lists in the repository root. ```python providers = _available_providers(Path("/workspace/home/cdn-ip-ranges")) # Returns: ["akamai", "aws", "bunny", ..., "vercel"] ``` -------------------------------- ### Parse Amnezia VPN JSON with Python Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Demonstrates loading and iterating through the Amnezia VPN JSON format using the standard json library. ```python import json with open("aws_amnezia_ipv4.json") as f: entries = json.load(f) for entry in entries: print(f"Route: {entry['hostname']}") ``` -------------------------------- ### Convert IP Lists for Keenetic Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Commands for converting IP provider lists into Keenetic-compatible route commands. ```bash python3 scripts/convert_for_keenetic.py [OPTIONS] ``` ```bash python3 scripts/convert_for_keenetic.py --providers aws cloudflare akamai python3 scripts/convert_for_keenetic.py --providers "aws,cloudflare,akamai" python3 scripts/convert_for_keenetic.py --providers aws ``` ```bash python3 scripts/convert_for_keenetic.py --all ``` ```bash python3 scripts/convert_for_keenetic.py --all --max-lines 2048 python3 scripts/convert_for_keenetic.py --providers aws --max-lines 512 ``` ```bash # Interactive: prompts user to select providers python3 scripts/convert_for_keenetic.py # Specific providers python3 scripts/convert_for_keenetic.py --providers aws cloudflare # All providers with custom route limit python3 scripts/convert_for_keenetic.py --all --max-lines 2048 # Comma-separated input python3 scripts/convert_for_keenetic.py --providers "aws,cloudflare,akamai" ``` -------------------------------- ### Set NETWORKSDB_API_KEY for update_cdn_lists.py Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Required for Vercel provider authentication. Missing this variable will raise a RuntimeError. ```bash export NETWORKSDB_API_KEY="your-api-key-here" python3 scripts/update_cdn_lists.py ``` ```text RuntimeError: vercel: NETWORKSDB_API_KEY environment variable is not set ``` -------------------------------- ### Run GeoIP Generator via CLI Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Command-line invocation of the external v2fly/geoip tool using a generated configuration file. ```bash go run github.com/v2fly/geoip@latest -c ``` -------------------------------- ### Execute CDN range update workflow Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Demonstrates the full pipeline for fetching, normalizing, aggregating, and writing AWS IP range data. ```python #!/usr/bin/env python3 from pathlib import Path from update_cdn_lists import ( fetch_aws_ranges, normalize_prefixes, aggregate_prefixes, write_provider_outputs ) # Fetch AWS ranges raw = list(fetch_aws_ranges()) # Normalize: validate, deduplicate, canonicalize normalized = normalize_prefixes("aws", raw) # Aggregate: collapse overlapping prefixes aggregated = aggregate_prefixes("aws", normalized) # Write all output formats write_provider_outputs("aws", aggregated) print(f"Generated {len(aggregated)} aggregated prefixes for AWS") ``` -------------------------------- ### Write plain text prefixes Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Writes a sequence of CIDR prefixes to a file, one per line. Overwrites existing files and uses UTF-8 encoding. ```python def write_plain(path: Path, prefixes: Sequence[PrefixEntry]) -> None ``` -------------------------------- ### parse_args() Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Parses command-line arguments for standalone script execution, returning a Namespace object with configuration defaults. ```APIDOC ## parse_args() ### Description Parses command-line arguments for standalone script execution. Returns an argparse.Namespace object containing configuration settings for database connection, DNS resolution, and output paths. ### Returns - **argparse.Namespace** - Object containing attributes: regions, crtsh_db_host, crtsh_db_port, crtsh_db_name, crtsh_db_user, crtsh_db_connect_timeout, resolver, workers, timeout, retries, max_domains, progress_every, domains_out, ips_out, json_out, resolved_domains_only. ``` -------------------------------- ### Define Tool Versions Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Specifies the versions for Python and Go environments used in the workflow. ```yaml python-version: "3.12" # Latest Python 3.12 minor version go-version: stable # Latest stable Go release ``` -------------------------------- ### Resolve Domain via System Resolver Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Resolves a domain to a sorted list of global IP addresses using the host's system resolver. Returns an empty list if resolution fails. ```python def resolve_domain_system(host: str) -> list[str] ``` ```python ips = resolve_domain_system("seattle-1.discord.gg") # Returns: ["1.2.3.4", "5.6.7.8", "2001:db8::1"] ``` -------------------------------- ### Set Workflow Environment Variables Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Configures the API key required for Vercel provider authentication via GitHub secrets. ```yaml env: NETWORKSDB_API_KEY: ${{ secrets.NETWORKSDB_API_KEY }} ``` -------------------------------- ### Chunk command lines in Python Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Splits a list of command strings into smaller sublists based on a maximum line count. ```python lines = ["line1", "line2", "line3", "line4"] chunks = _chunk_lines(lines, 2) # Returns: [["line1", "line2"], ["line3", "line4"]] ``` -------------------------------- ### Update IP Ranges Manually Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/INDEX.md Executes the full pipeline to fetch, generate binary formats, and verify changes in the repository. ```bash cd /workspace/home/cdn-ip-ranges # Set required API key for Vercel export NETWORKSDB_API_KEY="your-key" # Run main pipeline python3 scripts/update_cdn_lists.py # Generate binary formats python3 scripts/generate_geoip_dat.py python3 scripts/generate_sing_box_rulesets.py # Check for changes git status git diff aws/aws_plain_ipv4.txt | head -20 ``` -------------------------------- ### Run Collection Script via CLI Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Executes the collection script with specified regions and output paths. ```bash python3 scripts/collect_discord_voice_ips.py \ --regions "seattle,frankfurt,us-east" \ --resolver udp \ --workers 24 \ --timeout 5.0 \ --ips-out /tmp/discord_ips.txt \ --json-out /tmp/discord_report.json ``` -------------------------------- ### fetch_discord_voice_ranges() -> Sequence[PrefixEntry] Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Fetches Discord voice server IP ranges by resolving hostnames discovered via certificate transparency logs. ```APIDOC ## fetch_discord_voice_ranges() ### Description Fetch Discord voice server IP ranges via crt.sh certificate transparency database and DNS resolution. ### Returns - **Sequence[PrefixEntry]** - Individual IPv4 and IPv6 addresses (as /32 and /128 prefixes) with hostname labels. ``` -------------------------------- ### Parse CSV with Python Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md Demonstrates reading the CSV file using the standard csv.DictReader module. ```python import csv with open("all.csv") as f: reader = csv.DictReader(f) for row in reader: print(f"{row['provider']}: {row['cidr']} ({row['region']})") ``` -------------------------------- ### View Keenetic Output Paths Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Displays the structure for Keenetic-specific batch files, which may be split if route counts exceed limits. ```text scripts/ ├── aws_keenetic.bat # Single file if ≤ max-lines routes ├── aws_keenetic_1.bat # Multiple files if > max-lines ├── aws_keenetic_2.bat ├── cloudflare_keenetic.bat └── ... (per provider) ``` -------------------------------- ### Invoke sing-box CLI compilation Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Executes the sing-box binary to compile a JSON ruleset into the binary .srs format. ```bash rule-set compile -o ``` ```python convert_ruleset( Path("/usr/local/bin/sing-box"), Path("/tmp/aws-ruleset.json"), Path("aws/aws_singbox_ipv4.srs"), ) ``` -------------------------------- ### Build GeoIP Configuration Schema Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md The expected JSON structure for the v2fly/geoip configuration, defining input sources and output binary file specifications. ```json { "input": [ { "type": "text", "action": "add", "args": { "name": "provider", "uri": "/absolute/path/to/provider_plain.txt" } }, ... ], "output": [ { "type": "v2rayGeoIPDat", "action": "output", "args": { "outputDir": "/absolute/path/to/provider", "outputName": "provider_geoip.dat", "wantedList": ["provider"] } }, { "type": "v2rayGeoIPDat", "action": "output", "args": { "outputDir": "/absolute/path/to/provider", "outputName": "provider_geoip_ipv4.dat", "wantedList": ["provider"], "onlyIPType": "ipv4" } }, ... ] } ``` -------------------------------- ### Match region label with Python Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Tests if a domain label matches a specific region slug based on prefix and suffix rules. ```python _match_region_label("seattle-1", ["seattle", "frankfurt"]) # Returns: "seattle" _match_region_label("rtc", ["seattle", "frankfurt"]) # Returns: None ``` -------------------------------- ### Represent Filesystem Paths Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Utilizes the pathlib standard library to represent filesystem paths across different operating systems. ```python Path # Represents filesystem paths across platforms ``` -------------------------------- ### Write Amnezia VPN JSON Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Exports IPv4 prefixes to a JSON format compatible with Amnezia VPN. IPv6 prefixes are automatically filtered out. ```python def write_amnezia_ipv4_json(path: Path, prefixes: Sequence[PrefixEntry]) -> None ``` -------------------------------- ### Generate binary ruleset from CIDR list Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Converts a plaintext CIDR file into a temporary JSON ruleset and compiles it to a binary .srs file. ```json { "version": 3, "rules": [ { "ip_cidr": [ "192.0.2.0/24", "198.51.100.0/24", "2001:db8::/32", ... ] } ] } ``` ```python generate_ruleset( Path("sing-box"), Path("aws/aws_plain_ipv4.txt"), Path("aws/aws_singbox_ipv4.srs"), ) # Reads: aws/aws_plain_ipv4.txt (~1000 lines of CIDR) # Generates: aws/aws_singbox_ipv4.srs (binary file) ``` -------------------------------- ### Configure Mihomo Rule Provider Source: https://github.com/123jjck/cdn-ip-ranges/wiki/Usage-(EN) Define a rule provider in your Mihomo configuration to fetch IP CIDR lists from the repository. ```yaml rule-providers: cdn-ip-ranges-all: behavior: ipcidr type: http url: "https://raw.githubusercontent.com/123jjck/cdn-ip-ranges/refs/heads/main/all/all_plain_ipv4.txt" interval: 86400 format: text ``` -------------------------------- ### Fetch RIPE prefixes Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Retrieves IP ranges for a specific ASN from the RIPE NCC API. The ASN is automatically normalized to the required format. ```python prefixes = fetch_ripe_prefixes("13335") # Cloudflare # Also valid: fetch_ripe_prefixes("AS13335") # Returns ~300-500 PrefixEntry objects ``` -------------------------------- ### Generate Keenetic route commands in Python Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Converts a list of IPv4Network objects into a list of Keenetic route add commands. Note that all routes default to 0.0.0.0 as the gateway. ```python networks = [IPv4Network("192.0.2.0/24"), IPv4Network("198.51.100.0/24")] commands = _build_routes(networks) # Returns: [ # "route add 192.0.2.0 mask 255.255.255.0 0.0.0.0", # "route add 198.51.100.0 mask 255.255.255.0 0.0.0.0", # ] ``` -------------------------------- ### Write combined CSV Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Writes provider, CIDR, and region data to a CSV file. Uses standard CSV escaping and creates the output directory if it does not exist. ```python def write_combined_csv(name: str, entries: Sequence[tuple[str, PrefixEntry]]) -> None ``` -------------------------------- ### Access IP Network Attributes Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Demonstrates accessing common attributes of an ipaddress network object. ```python import ipaddress net = ipaddress.ip_network("192.0.2.0/24") print(net.network_address) # IPv4Address('192.0.2.0') print(net.version) # 4 print(net.prefixlen) # 24 print(net.netmask) # IPv4Address('255.255.255.0') ``` -------------------------------- ### fetch_ripe_prefixes(asn: str) -> Sequence[PrefixEntry] Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Fetches IP ranges for a specific Autonomous System Number (ASN) from the RIPE NCC public API. ```APIDOC ## fetch_ripe_prefixes(asn: str) ### Description Fetch IP ranges for an Autonomous System Number (ASN) from the RIPE NCC API. ### Parameters - **asn** (str) - Required - ASN in format "AS12345" or "12345"; normalized to "AS" prefix internally. ### Returns - **Sequence[PrefixEntry]** - IPv4 and IPv6 prefixes without region metadata. ``` -------------------------------- ### Parse provider arguments Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Determines the list of providers to process based on command-line arguments or interactive fallback. ```python # Command-line: python3 script.py --providers aws,cloudflare args = parse_args() selected = _parse_provider_args(args, ["akamai", "aws", "cloudflare"]) # Returns: ["aws", "cloudflare"] ``` -------------------------------- ### Define Provider-to-Prefixes Mapping Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Type alias for mapping provider names to lists of prefixes. ```python dict[str, List[PrefixEntry]] ``` -------------------------------- ### Collect Discord Voice IPs Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Executes the collection script with specified regions, resolver settings, and output paths. ```bash python3 scripts/collect_discord_voice_ips.py \ --regions "seattle,frankfurt,sydney" \ --resolver udp \ --workers 24 \ --timeout 5.0 \ --retries 3 \ --max-domains 1000 \ --progress-every 100 \ --ips-out /tmp/discord_ips.txt \ --json-out /tmp/discord_report.json \ --resolved-domains-only ``` -------------------------------- ### Programmatic IP Collection Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Integrates the collection logic into a Python application, requiring specific database and resolver configurations. ```python from pathlib import Path from collect_discord_voice_ips import collect_voice_domain_ips all_domains, by_region, resolved, errors = collect_voice_domain_ips( regions=["seattle", "frankfurt", "sydney"], db_host="crt.sh", db_port=5432, db_name="certwatch", db_user="guest", db_connect_timeout=20, resolver="udp", workers=24, timeout=5.0, retries=3, max_domains=0, progress_every=500, ) # Process results for domain, ips in resolved.items(): for ip in ips: print(f"{ip} # {domain}") if errors: print(f"Failed to resolve {len(errors)} domains") ``` -------------------------------- ### Programmatic GeoIP Generation Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Integrate the generation process into Python scripts by building the configuration and invoking the generator directly. ```python from pathlib import Path from generate_geoip_dat import build_geoip_config, run_geoip_generator import json # Build config config = build_geoip_config() config_path = Path("/tmp/geoip-config.json") config_path.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8") # Run generator run_geoip_generator(config_path) # Now .dat files exist in provider directories print("GeoIP files generated successfully") ``` -------------------------------- ### Primary Pipeline Architecture Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/INDEX.md Visual representation of the data flow in the primary update_cdn_lists.py pipeline. ```text fetch_aws_ranges() ──┐ fetch_oracle_ranges() ├─ normalize_prefixes() ─ aggregate_prefixes() ─ write_provider_outputs() fetch_ripe_prefixes() ├───────────────────────────────────────────────────────────────────── fetch_discord_voice_ranges() ┤ fetch_vercel_ranges() ┘ ``` -------------------------------- ### Programmatic ruleset generation Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-sing-box.md Use the generate_ruleset function within a Python script to process provider data into binary rulesets. ```python from pathlib import Path from generate_sing_box_rulesets import discover_providers, generate_ruleset providers = discover_providers(Path("/workspace/home/cdn-ip-ranges")) singbox_bin = Path("/usr/local/bin/sing-box") for provider in providers: provider_dir = Path("/workspace/home/cdn-ip-ranges") / provider # Generate full ruleset generate_ruleset( singbox_bin, provider_dir / f"{provider}_plain.txt", provider_dir / f"{provider}_singbox.srs", ) # Generate IPv4-only ruleset generate_ruleset( singbox_bin, provider_dir / f"{provider}_plain_ipv4.txt", provider_dir / f"{provider}_singbox_ipv4.srs", ) print(f"Generated {provider} rulesets") ``` -------------------------------- ### Generate GeoIP Data Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/configuration.md Commands for generating and compiling GeoIP data files. ```bash python3 scripts/generate_geoip_dat.py [OPTIONS] ``` ```bash python3 scripts/generate_geoip_dat.py --config-only --config-path /tmp/cfg.json cat /tmp/cfg.json # Review config # Then manually run: go run github.com/v2fly/geoip@latest -c /tmp/cfg.json ``` ```bash --config-path /tmp/geoip-config.json ``` ```bash # Generate and compile immediately python3 scripts/generate_geoip_dat.py # Generate config only python3 scripts/generate_geoip_dat.py --config-only --config-path /tmp/cfg.json # Generate config to specific path and compile python3 scripts/generate_geoip_dat.py --config-path /tmp/cfg.json ``` -------------------------------- ### resolve_domain_system(host: str) Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-collect-discord-voice.md Resolves a domain to IP addresses using the system resolver. ```APIDOC ## resolve_domain_system ### Description Resolve domain to IP addresses using system resolver (socket.getaddrinfo). Filters to global IP addresses only. ### Parameters - **host** (str) - Required - Domain name to resolve ### Returns - **list[str]** - Sorted list of global-scope IP addresses (IPv4 and IPv6) ``` -------------------------------- ### Plain Text IP List Format Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/output-formats.md A simple list of CIDR prefixes, one per line, used for manual inspection or basic tool integration. ```text 1.178.1.0/24 1.178.4.0/22 1.178.8.0/22 1.178.16.0/20 1.178.64.0/23 ... (continues) 2400:7fc0::/32 2600:1f00::/32 ... (IPv6 prefixes) ``` -------------------------------- ### Prompt for provider selection Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-keenetic.md Interactively requests provider names from the user via standard input. ```text Available providers: akamai, aws, bunny, ..., vercel Enter provider names separated by commas. > aws, cloudflare, akamai # Returns: ["aws", "cloudflare", "akamai"] ``` -------------------------------- ### Generate Keenetic Scripts Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/INDEX.md Converts IP lists into Keenetic-compatible batch scripts with optional gateway IP modification. ```bash # Interactive selection python3 scripts/convert_for_keenetic.py # Batch mode: all providers python3 scripts/convert_for_keenetic.py --all --max-lines 2048 # Edit for your gateway IP, then upload to router sed -i 's/0\.0\.0\.0$/192.168.1.100/g' aws_keenetic.bat ``` -------------------------------- ### Define GeoIP Configuration Structure Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Represents the dictionary structure generated by build_geoip_config() for input and output processing. ```python dict[str, Any] ``` ```json { "input": [ { "type": "text", "action": "add", "args": { "name": "provider", "uri": "/path/to/file", }, }, ... ], "output": [ { "type": "v2rayGeoIPDat", "action": "output", "args": { "outputDir": "/path", "outputName": "provider_geoip.dat", "wantedList": ["provider"], "onlyIPType": "ipv4", # Optional }, }, ... ], } ``` -------------------------------- ### Fetch raw text from a URL Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-update-cdn-lists.md Retrieves and decodes text from a URL with automatic retry logic for transient failures. ```python text = fetch_text("https://docs.oracle.com/iaas/tools/public_ip_ranges.json") # text is a JSON string; caller should parse with json.loads() ``` -------------------------------- ### Generate GeoIP dat files via GitHub Actions Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/api-reference-geoip-dat.md Invoke the generation script within a GitHub Actions workflow step. ```yaml - name: Generate GeoIP dat files run: python3 scripts/generate_geoip_dat.py ``` -------------------------------- ### Discord Voice Pipeline Architecture Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/INDEX.md Visual representation of the data flow in the collect_discord_voice_ips.py pipeline. ```text fetch_ct_domains_from_postgres() ─ extract_voice_domains() ─ resolve_all_domains() ─ collect_voice_domain_ips() ``` -------------------------------- ### Define Provider-Prefix Tuple Type Source: https://github.com/123jjck/cdn-ip-ranges/blob/main/_autodocs/types.md Represents a two-element tuple containing a provider name and a PrefixEntry object. ```python tuple[str, PrefixEntry] ``` ```python entries = [ ("aws", PrefixEntry("192.0.2.0/24", region="us-west-2")), ("cloudflare", PrefixEntry("198.51.100.0/24")), ] ```