import ipaddress from typing import List, Dict, Any, Optional, Union, Set, Iterable import requests class CDNRange: ipv4_ranges: List[ipaddress.IPv4Network] ipv6_ranges: List[ipaddress.IPv6Network] def __init__(self) -> None: self.ipv4_ranges = list() self.ipv6_ranges = list() class AWS(CDNRange): def __init__(self, *, data: Optional[Dict[str, Any]] = None) -> None: super().__init__() if data is None: data = requests.get("https://ip-ranges.amazonaws.com/ip-ranges.json").json() self.ipv4_ranges.extend([ipaddress.ip_network(p["ip_prefix"]) for p in data["prefixes"]]) # type: ignore[misc] self.ipv6_ranges.extend([ipaddress.ip_network(p["ipv6_prefix"]) for p in data["ipv6_prefixes"]]) # type: ignore[misc] class AWSCloudFront(CDNRange): def __init__(self, *, data: Optional[Dict[str, List[str]]] = None) -> None: super().__init__() if data is None: data = requests.get("https://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips").json() for key in data.keys(): for item in data[key]: network = ipaddress.ip_network(item) if isinstance(network, ipaddress.IPv4Network): self.ipv4_ranges.append(network) else: self.ipv6_ranges.append(network) class AzureFrontDoorBackend(CDNRange): def __init__(self, *, data: Optional[List[Dict[str, Any]]] = None) -> None: super().__init__() if data is None: data = requests.get( "https://azureipranges.azurewebsites.net/getPrefixes/Public/AzureFrontDoor.Backend").json() for item in data[0]["addressPrefixes"]: range = ipaddress.ip_network(item) if isinstance(range, ipaddress.IPv4Network): self.ipv4_ranges.append(range) else: self.ipv6_ranges.append(range) class Fastly(CDNRange): def __init__(self, *, data: Optional[Dict[str, List[str]]] = None) -> None: super().__init__() if data is None: data = requests.get("https://api.fastly.com/public-ip-list").json() self.ipv4_ranges.extend([ipaddress.ip_network(p) for p in data["addresses"]]) # type: ignore[misc] self.ipv6_ranges.extend([ipaddress.ip_network(p) for p in data["ipv6_addresses"]]) # type: ignore[misc] def all_cdn_prefixes() -> Iterable[str]: prefixes: Set[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]] = set() aws = AWS() prefixes.update(aws.ipv4_ranges) prefixes.update(aws.ipv6_ranges) azure = AzureFrontDoorBackend() prefixes.update(azure.ipv4_ranges) prefixes.update(azure.ipv6_ranges) fastly = Fastly() prefixes.update(fastly.ipv4_ranges) prefixes.update(fastly.ipv6_ranges) return [str(p) for p in prefixes]