Created
June 17, 2020 02:26
-
-
Save dadatuputi/858a1fea812666509aca29e1aa9043a5 to your computer and use it in GitHub Desktop.
Python countryblock with threshold
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests, argparse, pathlib | |
from itertools import accumulate | |
from operator import itemgetter | |
def build_subnet_list(country, threshold): | |
""" | |
Return a list of the largest subnets from the designated | |
country that provide coverage at least up to the threshold amount | |
""" | |
url = "https://geoblocks.dalleyfamily.net/api.php" | |
data = {'countries': country, 'aggregate': 'yes', 'ipver': '4', 'format': 'cidr', 'outputas': 'plaintext'} | |
request = requests.get(url, params = data) | |
assert request.status_code == 200 | |
# Split subnets by CIDR and sort by size of subnet | |
subnets = [tuple([sub, int(sub.split('/')[1])]) for sub in iter(request.text.splitlines())] | |
sort_subnets = sorted(subnets, key=itemgetter(1)) | |
# Build a list of how many ips are in each subnet | |
ips = [2**(32-sub[1]) for sub in sort_subnets] | |
total = sum(ips) | |
print("{} subnets ({} ips) in {}".format(len(subnets), total, country)) | |
# Build list of accumulating subnet coverage and find threshold | |
ip_percent = [r/total for r in accumulate(ips)] | |
for n, percent in enumerate(ip_percent): | |
if percent >= threshold: | |
break | |
print("{} subnets cover {:.2%} of ips".format(n, ip_percent[n])) | |
filter_list = [sub[0] for sub in sort_subnets[:n]] | |
return filter_list | |
# get args with argparse library: | |
# https://docs.python.org/3/library/argparse.html | |
parser = argparse.ArgumentParser(description='Build a list of subnets to block in CN/AU to avoid egress fees in gcloud') | |
parser.add_argument('env', type=pathlib.Path, help='specify an .env file to write the blocklist to - the ENV variables will be appended to the end') | |
parser.add_argument('-t', '--threshold', type=int, metavar='percentage', default=95, nargs='?', help='the percentage of ips you want to cover with the blocklist (default: %(default)s)') | |
args = parser.parse_args() | |
cn = build_subnet_list('CN', args.threshold/100) | |
au = build_subnet_list('AU', args.threshold/100) | |
with args.env.open('a') as f: | |
f.write('CN_BLOCK="' + ' '.join(cn) + '"\n') | |
f.write('AU_BLOCK="' + ' '.join(au) + '"\n') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment