IP sub-netting is one of the first things one learns about network administration.
You have a /22, you want /24′s, 2 bits give you 4 sub-nets. Or you want one /24, so you break the /22 into two /24′s and a /23. Not rocket science. It’s the kind of thing you can do in your head and keep track of in a spreadsheet or a text file if you don’t have too many networks.
When you’re planning an IP addressing scheme, you probably have the luxury of time, to think about it. But what if you need to do this in a crisis situation? Fortunately it has never happened to me, but I can think of scenarios where you need to do this very quickly:
Apparently, if you use BGP to advertise a network to the Internet and specific hosts within that network become the target of a DDoS attack, one way to mitigate the attack could be to stop advertising the /24 sub-nets being attacked. Although this means the attacker still succeeds in taking down his intended targets (because he made you take them down), at least you can remove the attack traffic from your link, and the rest of your network can remain available.
Another scenario might be someone hijacking part of your network by advertising a more specific route than you are (either intentionally, or due to a BGP filtering misconfiguration). This happened to youtube last year.
Either way, you’ll need to split the network into at least two (in the case of a /23) sub-nets to get a /24, which is generally the longest prefix accepted on the Internet. In the former case, you want to withdraw the more specific network, and in the latter you want to advertise it.
To this end, I have written a script that accepts a list of networks (in CIDR format, one per line) from STDIN, and the desired sub-net as the first command line argument. It loops through the input subnets, looking for the one that overlaps with the desired prefix. If a network doesn’t match, the script just prints it out untouched, if it does, then the script will de-aggregate that network into the minimum number of sub-nets in order to get the desired sub-net as one of the outputs. It prints the surrounding pieces, and unless you specify “-exclude” as the second argument, the desired sub-net itself is also added to the output:
#!/usr/bin/python # deaggregate.py - deaggregate a network for a specific subnet, yielding the minimum number of subnets # Add -exclude to only output the surrounding subnets. Subnet is read from stdin, all non matching subnets # are output untouched. Use as a filter, rinse, repeat. # Simeon Miteff <simeon@localloop.co.za> from IPy import IP import sys def split(ip,sub,exclude): if ip==sub: if not exclude: print ip else: a = IP(str(ip.net())+'/'+str(ip.prefixlen()+1)) b = IP(str(IP(ip.net().int()|2**(32-(ip.prefixlen()+1))))+'/'+str(ip.prefixlen()+1)) if a.overlaps(sub): print b split(a,sub,exclude) elif b.overlaps(sub): print a split(b,sub,exclude) if __name__=="__main__": if len(sys.argv)<2: sys.stderr.write("Usage: %s CIDR_prefix [-exclude]\n" % sys.argv[0]) sys.exit(1) sub = IP(sys.argv[1]) exclude = False if len(sys.argv)==3: if sys.argv[2]=='-exclude': exclude = True for line in sys.stdin: pre = IP(line.strip()) if not pre.overlaps(sub): print line.strip() else: split(pre,sub,exclude)
An example run:
simeon@capybara:~/personal$ cat routes.txt 10.0.0.0/10 192.168.0.0/16 simeon@capybara:~/personal$ python deaggregate.py 10.0.100.0/24 < routes.txt 10.32.0.0/11 10.16.0.0/12 10.8.0.0/13 10.4.0.0/14 10.2.0.0/15 10.1.0.0/16 10.0.128.0/17 10.0.0.0/18 10.0.64.0/19 10.0.112.0/20 10.0.104.0/21 10.0.96.0/22 10.0.102.0/23 10.0.101.0/24 10.0.100.0/24 192.168.0.0/16 simeon@capybara:~/personal$
It requires the IPy module (apt-get install python-ipy). To handle multiple desired sub-nets, run the script again for each subsequent sub-net, using the output of the previous run as the input. Note that your (and your upstream's) filters might need to be updated (unless your original prefix is allowed with something like "le 24").
I've added this to the code page. Thanks for listening :-)

Post a Comment