forked from dndx/nchnroutes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
produce.py
executable file
·112 lines (92 loc) · 3.26 KB
/
produce.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env python3
import argparse
import urllib.request
import csv
from ipaddress import IPv4Network, IPv6Network
import math
parser = argparse.ArgumentParser(description='Generate non-China routes for BIRD.')
parser.add_argument('--exclude', metavar='CIDR', type=str, nargs='*',
help='IPv4 ranges to exclude in CIDR format')
parser.add_argument('--next', default="wg0", metavar = "INTERFACE OR IP",
help='next hop for where non-China IP address, this is usually the tunnel interface')
args = parser.parse_args()
class Node:
def __init__(self, cidr, parent=None):
self.cidr = cidr
self.child = []
self.parent = parent
def __repr__(self):
return "<Node %s>" % self.cidr
def dump_tree(lst, ident=0):
for n in lst:
print("+" * ident + str(n))
dump_tree(n.child, ident + 1)
def dump_bird(lst, f):
for n in lst:
if len(n.child) > 0:
dump_bird(n.child, f)
else:
f.write('route %s via "%s";\n' % (n.cidr, args.next))
RESERVED = [
IPv4Network('0.0.0.0/8'),
IPv4Network('10.0.0.0/8'),
IPv4Network('127.0.0.0/8'),
IPv4Network('169.254.0.0/16'),
IPv4Network('172.16.0.0/12'),
IPv4Network('192.0.0.0/29'),
IPv4Network('192.0.0.170/31'),
IPv4Network('192.0.2.0/24'),
IPv4Network('192.168.0.0/16'),
IPv4Network('198.18.0.0/15'),
IPv4Network('198.51.100.0/24'),
IPv4Network('203.0.113.0/24'),
IPv4Network('240.0.0.0/4'),
IPv4Network('255.255.255.255/32'),
IPv4Network('169.254.0.0/16'),
IPv4Network('127.0.0.0/8'),
IPv4Network('224.0.0.0/4'),
IPv4Network('100.64.0.0/10'),
]
if args.exclude:
RESERVED += [IPv4Network(e) for e in args.exclude]
IPV6_UNICAST = IPv6Network('2000::/3')
def subtract_cidr(sub_from, sub_by):
for cidr_to_sub in sub_by:
for n in sub_from:
if n.cidr == cidr_to_sub:
n.parent.child.remove(n)
break
if n.cidr.supernet_of(cidr_to_sub):
if len(n.child) > 0:
subtract_cidr(n.child, sub_by)
else:
n.child = [Node(b, n) for b in n.cidr.address_exclude(cidr_to_sub)]
break
root = []
root_v6 = [Node(IPV6_UNICAST)]
with open("ipv4-address-space.csv", newline='') as f:
f.readline() # skip the title
reader = csv.reader(f, quoting=csv.QUOTE_MINIMAL)
for cidr in reader:
if cidr[5] == "ALLOCATED" or cidr[5] == "LEGACY":
block = cidr[0]
cidr = "%s.0.0.0%s" % (block[:3].lstrip("0"), block[-2:], )
root.append(Node(IPv4Network(cidr)))
# get rid of reserved addresses
subtract_cidr(root, RESERVED)
with open("delegated-apnic-latest") as f:
for line in f:
if "apnic|CN|ipv4|" in line:
line = line.split("|")
a = "%s/%d" % (line[3], 32 - math.log(int(line[4]), 2), )
a = IPv4Network(a)
subtract_cidr(root, (a,))
elif "apnic|CN|ipv6|" in line:
line = line.split("|")
a = "%s/%s" % (line[3], line[4])
a = IPv6Network(a)
subtract_cidr(root_v6, (a,))
with open("routes4.conf", "w") as f:
dump_bird(root, f)
with open("routes6.conf", "w") as f:
dump_bird(root_v6, f)