cloudcheck 8.7.2__pp311-pypy311_pp73-manylinux_2_17_i686.manylinux2014_i686.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudcheck/__init__.py +3 -0
- cloudcheck/cloudcheck.pypy311-pp73-x86-linux-gnu.so +0 -0
- cloudcheck/helpers.py +251 -0
- cloudcheck/providers/__init__.py +51 -0
- cloudcheck/providers/akamai.py +35 -0
- cloudcheck/providers/alibaba.py +13 -0
- cloudcheck/providers/amazon.py +39 -0
- cloudcheck/providers/arvancloud.py +22 -0
- cloudcheck/providers/backblaze.py +13 -0
- cloudcheck/providers/baidu.py +17 -0
- cloudcheck/providers/base.py +317 -0
- cloudcheck/providers/cachefly.py +26 -0
- cloudcheck/providers/cdnetworks.py +14 -0
- cloudcheck/providers/cisco.py +41 -0
- cloudcheck/providers/cloudflare.py +42 -0
- cloudcheck/providers/cloudfront.py +20 -0
- cloudcheck/providers/ddosguard.py +14 -0
- cloudcheck/providers/dell.py +13 -0
- cloudcheck/providers/digitalocean.py +32 -0
- cloudcheck/providers/dod.py +31 -0
- cloudcheck/providers/fastly.py +24 -0
- cloudcheck/providers/fbi.py +18 -0
- cloudcheck/providers/gabia.py +12 -0
- cloudcheck/providers/gcore.py +27 -0
- cloudcheck/providers/github.py +30 -0
- cloudcheck/providers/gocache.py +17 -0
- cloudcheck/providers/google.py +63 -0
- cloudcheck/providers/heroku.py +9 -0
- cloudcheck/providers/hetzner.py +20 -0
- cloudcheck/providers/hostway.py +13 -0
- cloudcheck/providers/hpe.py +14 -0
- cloudcheck/providers/huawei.py +19 -0
- cloudcheck/providers/ibm.py +59 -0
- cloudcheck/providers/imperva.py +27 -0
- cloudcheck/providers/kamatera.py +19 -0
- cloudcheck/providers/kinx.py +14 -0
- cloudcheck/providers/ktcloud.py +14 -0
- cloudcheck/providers/leaseweb.py +32 -0
- cloudcheck/providers/lgtelecom.py +13 -0
- cloudcheck/providers/microsoft.py +39 -0
- cloudcheck/providers/microsoft365.py +33 -0
- cloudcheck/providers/navercloud.py +15 -0
- cloudcheck/providers/nhncloud.py +15 -0
- cloudcheck/providers/oracle.py +33 -0
- cloudcheck/providers/ovh.py +17 -0
- cloudcheck/providers/qrator.py +16 -0
- cloudcheck/providers/quiccloud.py +38 -0
- cloudcheck/providers/rackspace.py +23 -0
- cloudcheck/providers/ru_fso.py +13 -0
- cloudcheck/providers/salesforce.py +17 -0
- cloudcheck/providers/scaleway.py +17 -0
- cloudcheck/providers/skbroadband.py +13 -0
- cloudcheck/providers/stormwall.py +14 -0
- cloudcheck/providers/sucuri.py +14 -0
- cloudcheck/providers/tencent.py +17 -0
- cloudcheck/providers/uk_mod.py +16 -0
- cloudcheck/providers/wasabi.py +17 -0
- cloudcheck/providers/x4b.py +14 -0
- cloudcheck/providers/yandex.py +107 -0
- cloudcheck/providers/zoho.py +27 -0
- cloudcheck/providers/zscaler.py +25 -0
- cloudcheck-8.7.2.dist-info/METADATA +252 -0
- cloudcheck-8.7.2.dist-info/RECORD +64 -0
- cloudcheck-8.7.2.dist-info/WHEEL +5 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import ipaddress
|
|
2
|
+
import os
|
|
3
|
+
import traceback
|
|
4
|
+
import subprocess
|
|
5
|
+
import time
|
|
6
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Dict, List, Union
|
|
9
|
+
from pydantic import BaseModel, field_validator, computed_field
|
|
10
|
+
|
|
11
|
+
from ..helpers import defrag_cidrs, parse_v2fly_domain_file, request
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
v2fly_repo_pulled = False
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BaseProvider(BaseModel):
|
|
18
|
+
"""
|
|
19
|
+
Base class for all cloud providers.
|
|
20
|
+
|
|
21
|
+
Each provider inherits from this class and overrides any of the default values.
|
|
22
|
+
They can also override the update_cidrs() method to fetch cidrs from a different source.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
# these values are static and always loaded from the class definition
|
|
26
|
+
regexes: Dict[str, List[str]] = {}
|
|
27
|
+
tags: List[str] = [] # Tags for the provider (e.g. "cdn", "waf", etc.)
|
|
28
|
+
org_ids: List[str] = [] # ASN Organization IDs (e.g. GOGL-ARIN)
|
|
29
|
+
v2fly_company: str = "" # Company name for v2fly domain fetching
|
|
30
|
+
short_description: str = "" # Short description of the provider
|
|
31
|
+
long_description: str = "" # Long description of the provider
|
|
32
|
+
|
|
33
|
+
# these values are dynamic and set by the update() method
|
|
34
|
+
last_updated: float = time.time()
|
|
35
|
+
|
|
36
|
+
# these we allow static values but they are later merged with dynamic values
|
|
37
|
+
asns: List[int] = []
|
|
38
|
+
cidrs: List[str] = []
|
|
39
|
+
domains: List[str] = []
|
|
40
|
+
|
|
41
|
+
@field_validator("cidrs")
|
|
42
|
+
@classmethod
|
|
43
|
+
def validate_cidrs(cls, value):
|
|
44
|
+
ips = []
|
|
45
|
+
for v in value:
|
|
46
|
+
try:
|
|
47
|
+
ips.append(ipaddress.ip_network(v, strict=False))
|
|
48
|
+
except ValueError:
|
|
49
|
+
print(f"Invalid CIDR: from {cls.__name__}: {v}")
|
|
50
|
+
continue
|
|
51
|
+
ips = [str(ip) for ip in defrag_cidrs(ips)]
|
|
52
|
+
return sorted(ips)
|
|
53
|
+
|
|
54
|
+
@field_validator("domains")
|
|
55
|
+
@classmethod
|
|
56
|
+
def validate_domains(cls, value):
|
|
57
|
+
return sorted(list(set([d.lower().strip(".") for d in value])))
|
|
58
|
+
|
|
59
|
+
@computed_field(return_type=str)
|
|
60
|
+
@property
|
|
61
|
+
def name(self):
|
|
62
|
+
return self.__class__.__name__
|
|
63
|
+
|
|
64
|
+
def __init__(self, **data):
|
|
65
|
+
super().__init__(**data)
|
|
66
|
+
self._cidrs = []
|
|
67
|
+
self._cache_dir = Path.home() / ".cache" / "cloudcheck"
|
|
68
|
+
self._repo_url = "https://github.com/v2fly/domain-list-community.git"
|
|
69
|
+
self._asndb_url = os.getenv("ASNDB_URL", "https://asndb.api.bbot.io/v1")
|
|
70
|
+
self._bbot_io_api_key = os.getenv("BBOT_IO_API_KEY")
|
|
71
|
+
|
|
72
|
+
def update(self):
|
|
73
|
+
print(f"Updating {self.name}")
|
|
74
|
+
errors = []
|
|
75
|
+
errors.extend(self.update_domains())
|
|
76
|
+
errors.extend(self.update_cidrs())
|
|
77
|
+
return errors
|
|
78
|
+
|
|
79
|
+
def update_domains(self):
|
|
80
|
+
# update dynamic domains
|
|
81
|
+
errors = []
|
|
82
|
+
domains = set()
|
|
83
|
+
|
|
84
|
+
# fetch any dynamically-updated lists of domains
|
|
85
|
+
try:
|
|
86
|
+
dynamic_domains = self.fetch_domains()
|
|
87
|
+
print(f"Got {len(dynamic_domains)} dynamic domains for {self.name}")
|
|
88
|
+
domains.update(dynamic_domains)
|
|
89
|
+
except Exception as e:
|
|
90
|
+
errors.append(
|
|
91
|
+
f"Failed to fetch dynamic domains for {self.name}: {e}:\n{traceback.format_exc()}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if self.v2fly_company:
|
|
95
|
+
_domains, _errors = self.fetch_v2fly_domains()
|
|
96
|
+
if _domains:
|
|
97
|
+
domains.update(_domains)
|
|
98
|
+
else:
|
|
99
|
+
errors.append(
|
|
100
|
+
f"No v2fly domains were found for {self.name} (company name: {self.v2fly_company})"
|
|
101
|
+
)
|
|
102
|
+
errors.extend(_errors)
|
|
103
|
+
|
|
104
|
+
# finally, put in any manually-specified domains
|
|
105
|
+
print(f"Adding {len(self.domains)} manually-specified domains for {self.name}")
|
|
106
|
+
if self.domains:
|
|
107
|
+
domains.update(self.domains)
|
|
108
|
+
|
|
109
|
+
print(f"Total {len(domains)} domains for {self.name}")
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
self.domains = self.validate_domains(domains)
|
|
113
|
+
except Exception as e:
|
|
114
|
+
errors.append(
|
|
115
|
+
f"Error validating domains for {self.name}: {e}:\n{traceback.format_exc()}"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
return errors
|
|
119
|
+
|
|
120
|
+
def update_cidrs(self):
|
|
121
|
+
cidrs = set()
|
|
122
|
+
errors = []
|
|
123
|
+
|
|
124
|
+
# query by direct ASNs
|
|
125
|
+
if self.asns:
|
|
126
|
+
_cidrs, _errors = self.fetch_asns()
|
|
127
|
+
print(f"Got {len(_cidrs)} ASN cidrs for {self.name}'s ASNs {self.asns}")
|
|
128
|
+
if not _cidrs:
|
|
129
|
+
errors.append(
|
|
130
|
+
f"No ASN cidrs were found for {self.name}'s ASNs {self.asns}"
|
|
131
|
+
)
|
|
132
|
+
errors.extend(_errors)
|
|
133
|
+
cidrs.update(_cidrs)
|
|
134
|
+
|
|
135
|
+
# query by org IDs
|
|
136
|
+
if self.org_ids:
|
|
137
|
+
_cidrs, _asns, _errors = self.fetch_org_ids()
|
|
138
|
+
_asns = _asns.copy()
|
|
139
|
+
_asns.update(self.asns)
|
|
140
|
+
self.asns = list(sorted(_asns))
|
|
141
|
+
print(
|
|
142
|
+
f"Got {len(_cidrs)} org id cidrs for {self.name}'s org ids {self.org_ids}"
|
|
143
|
+
)
|
|
144
|
+
if not _cidrs:
|
|
145
|
+
errors.append(
|
|
146
|
+
f"No cidrs were found for {self.name}'s org ids {self.org_ids}"
|
|
147
|
+
)
|
|
148
|
+
errors.extend(_errors)
|
|
149
|
+
cidrs.update(_cidrs)
|
|
150
|
+
|
|
151
|
+
# fetch any dynamically-updated lists of CIDRs
|
|
152
|
+
try:
|
|
153
|
+
dynamic_cidrs = self.fetch_cidrs()
|
|
154
|
+
print(f"Got {len(dynamic_cidrs)} dynamic cidrs for {self.name}")
|
|
155
|
+
cidrs.update(dynamic_cidrs)
|
|
156
|
+
except Exception as e:
|
|
157
|
+
errors.append(
|
|
158
|
+
f"Failed to fetch dynamic cidrs for {self.name}: {e}:\n{traceback.format_exc()}"
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# finally, put in any manually-specified CIDRs
|
|
162
|
+
print(f"Adding {len(self.cidrs)} manually-specified cidrs for {self.name}")
|
|
163
|
+
if self.cidrs:
|
|
164
|
+
cidrs.update(self.cidrs)
|
|
165
|
+
|
|
166
|
+
print(f"Total {len(cidrs)} cidrs for {self.name}")
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
self.cidrs = self.validate_cidrs(cidrs)
|
|
170
|
+
except Exception as e:
|
|
171
|
+
errors.append(
|
|
172
|
+
f"Error validating ASN cidrs for {self.name}: {e}:\n{traceback.format_exc()}"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
self.last_updated = time.time()
|
|
176
|
+
|
|
177
|
+
return errors
|
|
178
|
+
|
|
179
|
+
def _fetch_org_id(self, org_id: str):
|
|
180
|
+
"""Fetch ASNs for a single org_id."""
|
|
181
|
+
print(f"Fetching cidrs for {org_id} from asndb")
|
|
182
|
+
try:
|
|
183
|
+
url = f"{self._asndb_url}/org/{org_id}"
|
|
184
|
+
print(f"Fetching {url}")
|
|
185
|
+
res = self.request(url, include_api_key=True)
|
|
186
|
+
print(f"{url} -> {res}: {res.text}")
|
|
187
|
+
j = res.json()
|
|
188
|
+
return j.get("asns", []), []
|
|
189
|
+
except Exception as e:
|
|
190
|
+
error = f"Failed to fetch cidrs for {org_id} from asndb: {e}:\n{traceback.format_exc()}"
|
|
191
|
+
return [], [error]
|
|
192
|
+
|
|
193
|
+
def fetch_org_ids(
|
|
194
|
+
self,
|
|
195
|
+
) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
|
|
196
|
+
"""Takes org_ids and populates the .asns and .cidrs attributes."""
|
|
197
|
+
errors = []
|
|
198
|
+
cidrs = set()
|
|
199
|
+
print(f"Fetching {len(self.org_ids)} org ids for {self.name}")
|
|
200
|
+
asns = set()
|
|
201
|
+
|
|
202
|
+
# Parallelize org_id fetching
|
|
203
|
+
with ThreadPoolExecutor() as executor:
|
|
204
|
+
org_futures = {
|
|
205
|
+
executor.submit(self._fetch_org_id, org_id): org_id
|
|
206
|
+
for org_id in self.org_ids
|
|
207
|
+
}
|
|
208
|
+
for future in as_completed(org_futures):
|
|
209
|
+
_asns, _errors = future.result()
|
|
210
|
+
errors.extend(_errors)
|
|
211
|
+
asns.update(_asns)
|
|
212
|
+
|
|
213
|
+
# Parallelize ASN fetching
|
|
214
|
+
with ThreadPoolExecutor() as executor:
|
|
215
|
+
asn_futures = {executor.submit(self.fetch_asn, asn): asn for asn in asns}
|
|
216
|
+
for future in as_completed(asn_futures):
|
|
217
|
+
asn_cidrs, _errors = future.result()
|
|
218
|
+
errors.extend(_errors)
|
|
219
|
+
cidrs.update(asn_cidrs)
|
|
220
|
+
|
|
221
|
+
return cidrs, asns, errors
|
|
222
|
+
|
|
223
|
+
def fetch_asns(self) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
|
|
224
|
+
"""Fetch CIDRs for a given list of ASNs from ASNDB."""
|
|
225
|
+
cidrs = []
|
|
226
|
+
errors = []
|
|
227
|
+
print(f"Fetching {len(self.asns)} ASNs for {self.name}")
|
|
228
|
+
for asn in self.asns:
|
|
229
|
+
asn_cidrs, _errors = self.fetch_asn(asn)
|
|
230
|
+
errors.extend(_errors)
|
|
231
|
+
cidrs.update(asn_cidrs)
|
|
232
|
+
return cidrs, errors
|
|
233
|
+
|
|
234
|
+
def fetch_asn(
|
|
235
|
+
self, asn: int
|
|
236
|
+
) -> List[Union[ipaddress.IPv4Network, ipaddress.IPv6Network]]:
|
|
237
|
+
"""Fetch CIDRs for a given ASN from ASNDB."""
|
|
238
|
+
cidrs = []
|
|
239
|
+
errors = []
|
|
240
|
+
url = f"{self._asndb_url}/asn/{asn}"
|
|
241
|
+
print(f"Fetching {url}")
|
|
242
|
+
try:
|
|
243
|
+
res = self.request(url, include_api_key=True)
|
|
244
|
+
print(f"{url} -> {res.text}")
|
|
245
|
+
j = res.json()
|
|
246
|
+
cidrs = j.get("subnets", [])
|
|
247
|
+
except Exception as e:
|
|
248
|
+
errors.append(
|
|
249
|
+
f"Failed to fetch cidrs for {asn} from asndb: {e}:\n{traceback.format_exc()}"
|
|
250
|
+
)
|
|
251
|
+
print(f"Got {len(cidrs)} cidrs for {asn}")
|
|
252
|
+
return cidrs, errors
|
|
253
|
+
|
|
254
|
+
def fetch_v2fly_domains(self) -> List[str]:
|
|
255
|
+
"""Fetch domains from the v2fly community repository."""
|
|
256
|
+
if not self.v2fly_company:
|
|
257
|
+
return [], []
|
|
258
|
+
|
|
259
|
+
errors = []
|
|
260
|
+
repo_path, _success = self._ensure_v2fly_repo_cached()
|
|
261
|
+
company_file = repo_path / "data" / self.v2fly_company
|
|
262
|
+
try:
|
|
263
|
+
domains = parse_v2fly_domain_file(company_file)
|
|
264
|
+
except Exception as e:
|
|
265
|
+
errors.append(
|
|
266
|
+
f"Failed to parse {self.v2fly_company} domains: {e}:\n{traceback.format_exc()}"
|
|
267
|
+
)
|
|
268
|
+
return sorted(list(domains)), errors
|
|
269
|
+
|
|
270
|
+
def fetch_cidrs(self) -> List[str]:
|
|
271
|
+
"""Fetch CIDRs from a custom source."""
|
|
272
|
+
return []
|
|
273
|
+
|
|
274
|
+
def fetch_domains(self) -> List[str]:
|
|
275
|
+
"""Fetch domains from a custom source."""
|
|
276
|
+
return []
|
|
277
|
+
|
|
278
|
+
def _ensure_v2fly_repo_cached(self) -> Path:
|
|
279
|
+
"""Ensure the community repo is cloned and up-to-date."""
|
|
280
|
+
global v2fly_repo_pulled
|
|
281
|
+
errors = []
|
|
282
|
+
repo_dir = self._cache_dir / "domain-list-community"
|
|
283
|
+
if not repo_dir.exists():
|
|
284
|
+
self._cache_dir.mkdir(parents=True, exist_ok=True)
|
|
285
|
+
try:
|
|
286
|
+
subprocess.run(
|
|
287
|
+
["git", "clone", "--depth", "1", self._repo_url, str(repo_dir)],
|
|
288
|
+
check=True,
|
|
289
|
+
capture_output=True,
|
|
290
|
+
)
|
|
291
|
+
v2fly_repo_pulled = True
|
|
292
|
+
except subprocess.CalledProcessError as e:
|
|
293
|
+
errors.append(
|
|
294
|
+
f"Failed to clone v2fly repo: {e}:\n{traceback.format_exc()}"
|
|
295
|
+
)
|
|
296
|
+
elif not v2fly_repo_pulled:
|
|
297
|
+
try:
|
|
298
|
+
subprocess.run(
|
|
299
|
+
["git", "pull"], cwd=repo_dir, check=True, capture_output=True
|
|
300
|
+
)
|
|
301
|
+
except subprocess.CalledProcessError as e:
|
|
302
|
+
errors.append(
|
|
303
|
+
f"Failed to pull v2fly repo: {e}:\n{traceback.format_exc()}"
|
|
304
|
+
)
|
|
305
|
+
return repo_dir, errors
|
|
306
|
+
|
|
307
|
+
def request(self, *args, **kwargs):
|
|
308
|
+
headers = kwargs.get("headers", {})
|
|
309
|
+
headers["x-rate-limit-blocking"] = "true"
|
|
310
|
+
kwargs["headers"] = headers
|
|
311
|
+
return request(*args, **kwargs)
|
|
312
|
+
|
|
313
|
+
def __str__(self):
|
|
314
|
+
return self.name
|
|
315
|
+
|
|
316
|
+
def __repr__(self):
|
|
317
|
+
return f"{self.__class__.__name__}(name='{self.name}')"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cachefly(BaseProvider):
|
|
6
|
+
tags: List[str] = ["cdn"]
|
|
7
|
+
short_description: str = "CacheFly"
|
|
8
|
+
long_description: str = (
|
|
9
|
+
"A content delivery network provider offering global CDN services."
|
|
10
|
+
)
|
|
11
|
+
# {"org_id": "CL-1923-ARIN", "org_name": "CacheFly", "country": "US", "asns": [30081]}
|
|
12
|
+
org_ids: List[str] = [
|
|
13
|
+
"CL-1923-ARIN",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
_ips_url = "https://cachefly.cachefly.net/ips/rproxy.txt"
|
|
17
|
+
|
|
18
|
+
def fetch_cidrs(self):
|
|
19
|
+
response = self.request(self._ips_url)
|
|
20
|
+
ranges = set()
|
|
21
|
+
if getattr(response, "status_code", 0) == 200:
|
|
22
|
+
for line in response.text.splitlines():
|
|
23
|
+
line = line.strip()
|
|
24
|
+
if line and not line.startswith("#"):
|
|
25
|
+
ranges.add(line)
|
|
26
|
+
return list(ranges)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cdnetworks(BaseProvider):
|
|
6
|
+
tags: List[str] = ["cdn"]
|
|
7
|
+
short_description: str = "CDNetworks (씨디네트웍스)"
|
|
8
|
+
long_description: str = (
|
|
9
|
+
"A Korean content delivery network provider offering CDN and cloud services."
|
|
10
|
+
)
|
|
11
|
+
# {"org_id": "CDNET-ARIN", "org_name": "CDNetworks Inc.", "country": "US", "asns": [36408,40366]}
|
|
12
|
+
org_ids: List[str] = [
|
|
13
|
+
"CDNET-ARIN",
|
|
14
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cisco(BaseProvider):
|
|
6
|
+
v2fly_company: str = "cisco"
|
|
7
|
+
tags: List[str] = ["cloud"]
|
|
8
|
+
short_description: str = "Cisco"
|
|
9
|
+
long_description: str = "A multinational technology corporation that designs, manufactures, and sells networking hardware, software, and telecommunications equipment."
|
|
10
|
+
# {"org_id": "CISCO-25-ARIN", "org_name": "Cisco Systems Inc.", "country": "US", "asns": [25949]}
|
|
11
|
+
# {"org_id": "CISCO-32-ARIN", "org_name": "Cisco Systems, Inc.", "country": "US", "asns": [63096]}
|
|
12
|
+
# {"org_id": "CISCOR-ARIN", "org_name": "CIS Corporation", "country": "US", "asns": [3792]}
|
|
13
|
+
# {"org_id": "CISL-7-ARIN", "org_name": "Cisco Systems Ironport Division", "country": "US", "asns": [16417,30214,30215,30238,40427]}
|
|
14
|
+
# {"org_id": "CS-2787-ARIN", "org_name": "Cisco Systems Inc", "country": "US", "asns": [398699]}
|
|
15
|
+
# {"org_id": "CS-2821-ARIN", "org_name": "Cisco IoT", "country": "US", "asns": [36180,393544]}
|
|
16
|
+
# {"org_id": "CS-2825-ARIN", "org_name": "Cisco Systems, Inc.", "country": "US", "asns": [396922]}
|
|
17
|
+
# {"org_id": "CS-2831-ARIN", "org_name": "CISCO SYSTEMS, INC.", "country": "US", "asns": [109,2051,3943,22183,23460,26092,36519,40590,54140,399780]}
|
|
18
|
+
# {"org_id": "CS-691-ARIN", "org_name": "Cisco Systems Cloud Division", "country": "US", "asns": [1343,32644]}
|
|
19
|
+
# {"org_id": "CS-985-ARIN", "org_name": "Cisco Systems, Inc.", "country": "US", "asns": [55219]}
|
|
20
|
+
# {"org_id": "OPEND-2-ARIN", "org_name": "Cisco OpenDNS, LLC", "country": "US", "asns": [25605,30607,36692]}
|
|
21
|
+
# {"org_id": "ORG-CIL21-RIPE", "org_name": "Cisco International Limited", "country": "GB", "asns": [201799]}
|
|
22
|
+
# {"org_id": "ORG-CL586-RIPE", "org_name": "CISCOM Ltd", "country": "RU", "asns": [61035]}
|
|
23
|
+
# {"org_id": "ORG-CSNA1-RIPE", "org_name": "Cisco Systems Norway AS", "country": "NO", "asns": [58298]}
|
|
24
|
+
# {"org_id": "WEX-ARIN", "org_name": "Cisco Webex LLC", "country": "US", "asns": [6577,13445,16472,26152,53258,399937]}
|
|
25
|
+
org_ids: List[str] = [
|
|
26
|
+
"CISCO-25-ARIN",
|
|
27
|
+
"CISCO-32-ARIN",
|
|
28
|
+
"CISCOR-ARIN",
|
|
29
|
+
"CISL-7-ARIN",
|
|
30
|
+
"CS-2787-ARIN",
|
|
31
|
+
"CS-2821-ARIN",
|
|
32
|
+
"CS-2825-ARIN",
|
|
33
|
+
"CS-2831-ARIN",
|
|
34
|
+
"CS-691-ARIN",
|
|
35
|
+
"CS-985-ARIN",
|
|
36
|
+
"OPEND-2-ARIN",
|
|
37
|
+
"ORG-CIL21-RIPE",
|
|
38
|
+
"ORG-CL586-RIPE",
|
|
39
|
+
"ORG-CSNA1-RIPE",
|
|
40
|
+
"WEX-ARIN",
|
|
41
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cloudflare(BaseProvider):
|
|
6
|
+
v2fly_company: str = "cloudflare"
|
|
7
|
+
tags: List[str] = ["cdn"]
|
|
8
|
+
short_description: str = "Cloudflare"
|
|
9
|
+
long_description: str = "A web infrastructure and security company providing content delivery network services, DDoS mitigation, and web security solutions."
|
|
10
|
+
# {"org_id": "CLOUD14-ARIN", "org_name": "Cloudflare, Inc.", "country": "US", "asns": [13335,14789,394536,395747,400095]}
|
|
11
|
+
# {"org_id": "ORG-CHKL1-AP-APNIC", "org_name": "Cloudflare Hong Kong, LLC", "country": "US", "asns": [133877]}
|
|
12
|
+
# {"org_id": "ORG-CI4-AP-APNIC", "org_name": "Cloudflare, Inc.", "country": "US", "asns": [132892]}
|
|
13
|
+
# {"org_id": "ORG-CI40-RIPE", "org_name": "Cloudflare Inc", "country": "US", "asns": [202623,203898]}
|
|
14
|
+
# {"org_id": "ORG-CLL6-RIPE", "org_name": "Cloudflare London, LLC", "country": "US", "asns": [209242]}
|
|
15
|
+
# {"org_id": "ORG-CSL5-AP-APNIC", "org_name": "Cloudflare Sydney, LLC", "country": "US", "asns": [139242]}
|
|
16
|
+
org_ids: List[str] = [
|
|
17
|
+
"CLOUD14-ARIN",
|
|
18
|
+
"ORG-CHKL1-AP-APNIC",
|
|
19
|
+
"ORG-CI4-AP-APNIC",
|
|
20
|
+
"ORG-CI40-RIPE",
|
|
21
|
+
"ORG-CLL6-RIPE",
|
|
22
|
+
"ORG-CSL5-AP-APNIC",
|
|
23
|
+
]
|
|
24
|
+
_bucket_name_regex = r"[a-z0-9_][a-z0-9-\.]{1,61}[a-z0-9]"
|
|
25
|
+
regexes: Dict[str, List[str]] = {
|
|
26
|
+
"STORAGE_BUCKET_NAME": [_bucket_name_regex],
|
|
27
|
+
"STORAGE_BUCKET_HOSTNAME": [
|
|
28
|
+
r"(" + _bucket_name_regex + r")\.(r2\.dev)",
|
|
29
|
+
r"(" + _bucket_name_regex + r")\.(r2\.cloudflarestorage\.com)",
|
|
30
|
+
],
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
_ips_url = "https://api.cloudflare.com/client/v4/ips"
|
|
34
|
+
|
|
35
|
+
def fetch_cidrs(self):
|
|
36
|
+
response = self.request(self._ips_url)
|
|
37
|
+
ranges = set()
|
|
38
|
+
response_json = response.json()
|
|
39
|
+
for ip_type in ("ipv4_cidrs", "ipv6_cidrs"):
|
|
40
|
+
for ip_range in response_json.get("result", {}).get(ip_type, []):
|
|
41
|
+
ranges.add(ip_range)
|
|
42
|
+
return list(ranges)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cloudfront(BaseProvider):
|
|
6
|
+
tags: List[str] = ["cdn"]
|
|
7
|
+
short_description: str = "Amazon CloudFront"
|
|
8
|
+
long_description: str = "A content delivery network service provided by Amazon Web Services that delivers data, videos, applications, and APIs to customers globally."
|
|
9
|
+
|
|
10
|
+
_ips_url = "https://d7uri8nf7uskq.cloudfront.net/tools/list-cloudfront-ips"
|
|
11
|
+
|
|
12
|
+
def fetch_cidrs(self):
|
|
13
|
+
response = self.request(self._ips_url)
|
|
14
|
+
ranges = set()
|
|
15
|
+
response_json = response.json()
|
|
16
|
+
if not isinstance(response_json, dict):
|
|
17
|
+
raise ValueError(f"Invalid response format: {type(response_json)}")
|
|
18
|
+
for r in response_json.values():
|
|
19
|
+
ranges.update(r)
|
|
20
|
+
return list(ranges)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DDoSGuard(BaseProvider):
|
|
6
|
+
tags: List[str] = ["cdn"]
|
|
7
|
+
short_description: str = "DDoS Guard"
|
|
8
|
+
long_description: str = (
|
|
9
|
+
"A DDoS protection and content delivery network service provider."
|
|
10
|
+
)
|
|
11
|
+
# {"org_id": "ORG-DL236-RIPE", "org_name": "DDOS-GUARD LTD", "country": "RU", "asns": [44556,49612,57724]}
|
|
12
|
+
org_ids: List[str] = [
|
|
13
|
+
"ORG-DL236-RIPE",
|
|
14
|
+
]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Dell(BaseProvider):
|
|
6
|
+
v2fly_company: str = "dell"
|
|
7
|
+
tags: List[str] = ["cloud"]
|
|
8
|
+
short_description: str = "Dell"
|
|
9
|
+
long_description: str = "A multinational technology company that develops, sells, repairs, and supports computers and related products and services."
|
|
10
|
+
# {"org_id": "DCC-25-ARIN", "org_name": "Dell, Inc.", "country": "US", "asns": [3612,3613,3614,3615,7977,12257,14876,17187,23144,30614,46507,46977,53878,54701,64208]}
|
|
11
|
+
org_ids: List[str] = [
|
|
12
|
+
"DCC-25-ARIN",
|
|
13
|
+
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import csv
|
|
2
|
+
from cloudcheck.providers.base import BaseProvider
|
|
3
|
+
from typing import List, Dict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DigitalOcean(BaseProvider):
|
|
7
|
+
v2fly_company: str = "digitalocean"
|
|
8
|
+
tags: List[str] = ["cloud"]
|
|
9
|
+
short_description: str = "DigitalOcean"
|
|
10
|
+
long_description: str = "A cloud infrastructure provider offering virtual private servers, managed databases, and other cloud services for developers and businesses."
|
|
11
|
+
# {"org_id": "DO-13-ARIN", "org_name": "DigitalOcean, LLC", "country": "US", "asns": [14061,46652,62567,393406,394362]}
|
|
12
|
+
org_ids: List[str] = [
|
|
13
|
+
"DO-13-ARIN",
|
|
14
|
+
]
|
|
15
|
+
_bucket_name_regex = r"[a-z0-9][a-z0-9-]{2,62}"
|
|
16
|
+
regexes: Dict[str, List[str]] = {
|
|
17
|
+
"STORAGE_BUCKET_NAME": [_bucket_name_regex],
|
|
18
|
+
"STORAGE_BUCKET_HOSTNAME": [
|
|
19
|
+
r"(" + _bucket_name_regex + r")\.([a-z]{3}[\d]{1}\.digitaloceanspaces\.com)"
|
|
20
|
+
],
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_ips_url = "https://www.digitalocean.com/geo/google.csv"
|
|
24
|
+
|
|
25
|
+
def fetch_cidrs(self):
|
|
26
|
+
response = self.request(self._ips_url)
|
|
27
|
+
do_ips = csv.DictReader(
|
|
28
|
+
response.content.decode("utf-8").splitlines(),
|
|
29
|
+
fieldnames=["range", "country", "region", "city", "postcode"],
|
|
30
|
+
)
|
|
31
|
+
ranges = set(i["range"] for i in do_ips)
|
|
32
|
+
return list(ranges)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DoD(BaseProvider):
|
|
6
|
+
"""Department of Defense"""
|
|
7
|
+
|
|
8
|
+
tags: List[str] = ["gov"]
|
|
9
|
+
short_description: str = "Department of Defense"
|
|
10
|
+
long_description: str = "A U.S. government agency responsible for coordinating and supervising all agencies and functions of the government directly related to national security and the United States Armed Forces."
|
|
11
|
+
org_ids: List[str] = [
|
|
12
|
+
"USDDD-ARIN",
|
|
13
|
+
]
|
|
14
|
+
domains: List[str] = ["defense.gov", "war.gov", "mil"]
|
|
15
|
+
|
|
16
|
+
# https://en.wikipedia.org/wiki/List_of_assigned_/8_IPv4_address_blocks
|
|
17
|
+
cidrs: List[str] = [
|
|
18
|
+
"6.0.0.0/8", # Army Information Systems Center
|
|
19
|
+
"7.0.0.0/8", # DoD Network Information Center
|
|
20
|
+
"11.0.0.0/8", # DoD Intel Information Systems
|
|
21
|
+
"21.0.0.0/8", # DDN-RVN
|
|
22
|
+
"22.0.0.0/8", # Defense Information Systems Agency
|
|
23
|
+
"26.0.0.0/8", # Defense Information Systems Agency
|
|
24
|
+
"28.0.0.0/8", # DSI-North
|
|
25
|
+
"29.0.0.0/8", # Defense Information Systems Agency
|
|
26
|
+
"30.0.0.0/8", # Defense Information Systems Agency
|
|
27
|
+
"33.0.0.0/8", # DLA Systems Automation Center
|
|
28
|
+
"55.0.0.0/8", # DoD Network Information Center
|
|
29
|
+
"214.0.0.0/8", # DoD Network Information Center
|
|
30
|
+
"215.0.0.0/8", # DoD Network Information Center
|
|
31
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Fastly(BaseProvider):
|
|
6
|
+
v2fly_company: str = "fastly"
|
|
7
|
+
tags: List[str] = ["cdn"]
|
|
8
|
+
short_description: str = "Fastly"
|
|
9
|
+
long_description: str = "A content delivery network and edge cloud platform that provides edge computing, security, and performance services."
|
|
10
|
+
# {"org_id": "SKYCA-3-ARIN", "org_name": "Fastly, Inc.", "country": "US", "asns": [895,54113,394192]}
|
|
11
|
+
org_ids: List[str] = [
|
|
12
|
+
"SKYCA-3-ARIN",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
_ips_url = "https://api.fastly.com/public-ip-list"
|
|
16
|
+
|
|
17
|
+
def fetch_cidrs(self):
|
|
18
|
+
response = self.request(self._ips_url)
|
|
19
|
+
j = response.json()
|
|
20
|
+
if j and isinstance(j, dict):
|
|
21
|
+
addresses = j.get("addresses", [])
|
|
22
|
+
if addresses and isinstance(addresses, list):
|
|
23
|
+
return list(set(addresses))
|
|
24
|
+
return []
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class FBI(BaseProvider):
|
|
6
|
+
"""Federal Bureau of Investigation"""
|
|
7
|
+
|
|
8
|
+
tags: List[str] = ["gov"]
|
|
9
|
+
short_description: str = "Federal Bureau of Investigation"
|
|
10
|
+
long_description: str = "A U.S. government agency that serves as the domestic intelligence and security service, responsible for investigating federal crimes and protecting national security."
|
|
11
|
+
org_ids: List[str] = [
|
|
12
|
+
"FCJIS-ARIN", # Federal Criminal Justice Information Services
|
|
13
|
+
]
|
|
14
|
+
domains: List[str] = [
|
|
15
|
+
"fbi.gov",
|
|
16
|
+
"fbijobs.gov",
|
|
17
|
+
"ic3.gov",
|
|
18
|
+
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Gabia(BaseProvider):
|
|
6
|
+
tags: List[str] = ["cloud"]
|
|
7
|
+
short_description: str = "Gabia (가비아)"
|
|
8
|
+
long_description: str = "A Korean cloud hosting and infrastructure provider."
|
|
9
|
+
# {"org_id": "@aut-17589-APNIC", "org_name": null, "country": null, "asns": [17589]}
|
|
10
|
+
org_ids: List[str] = [
|
|
11
|
+
"@aut-17589-APNIC",
|
|
12
|
+
]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from cloudcheck.providers.base import BaseProvider
|
|
2
|
+
from typing import List
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Gcore(BaseProvider):
|
|
6
|
+
tags: List[str] = ["cdn"]
|
|
7
|
+
short_description: str = "G-Core Labs"
|
|
8
|
+
long_description: str = "A content delivery network and cloud infrastructure provider offering CDN, cloud computing, and edge services."
|
|
9
|
+
# {"org_id": "ORG-GLS1-AP-APNIC", "org_name": "G-Core Labs S.A", "country": "LU", "asns": [59245]}
|
|
10
|
+
# {"org_id": "ORG-WIG6-RIPE", "org_name": "G-Core Labs S.A.", "country": "LU", "asns": [199524,202422,210559]}
|
|
11
|
+
org_ids: List[str] = [
|
|
12
|
+
"ORG-GLS1-AP-APNIC",
|
|
13
|
+
"ORG-WIG6-RIPE",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
_ips_url = "https://api.gcore.com/cdn/public-ip-list"
|
|
17
|
+
|
|
18
|
+
def fetch_cidrs(self):
|
|
19
|
+
response = self.request(self._ips_url)
|
|
20
|
+
ranges = set()
|
|
21
|
+
if getattr(response, "status_code", 0) == 200:
|
|
22
|
+
response_json = response.json()
|
|
23
|
+
if isinstance(response_json, dict):
|
|
24
|
+
for key in "addresses", "addresses_v6":
|
|
25
|
+
for ip_range in response_json.get(key, []):
|
|
26
|
+
ranges.add(ip_range)
|
|
27
|
+
return list(ranges)
|