Skip to content

Instantly share code, notes, and snippets.

@dadatuputi
Created June 17, 2020 02:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dadatuputi/858a1fea812666509aca29e1aa9043a5 to your computer and use it in GitHub Desktop.
Save dadatuputi/858a1fea812666509aca29e1aa9043a5 to your computer and use it in GitHub Desktop.
Python countryblock with threshold
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